From nicholas at mxc.ca Mon Apr 20 00:18:05 2009 From: nicholas at mxc.ca (Nick Lewycky) Date: Sun, 19 Apr 2009 22:18:05 -0700 Subject: [llvm-commits] [llvm] r69531 - /llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp In-Reply-To: <200904191832.n3JIW3se017881@zion.cs.uiuc.edu> References: <200904191832.n3JIW3se017881@zion.cs.uiuc.edu> Message-ID: <49EC058D.1060203@mxc.ca> This causes a 'make check' failure on x86-64 linux with Ocaml installed. The problem seems to me to be that test/Bindings/Ocaml/executionengine.ml test_executionengine() never calls freeMachineCodeForFunction on @plus. I tried adding what I thought was the obvious statement and it still doesn't work. I don't know ocaml, but it seems that this statement looks up @plus and assigns it to "plus" if found: match ExecutionEngine.find_function "plus" ee with | None -> raise (Failure "find_function 'plus' failed") | Some plus -> and after the call to run_function, I added: ExecutionEngine.free_machine_code plus ee; but the test still fails: Failed with signal(SIGABRT) at line 2 while running: ./executionengine.ml.tmp executionengine.ml.tmp.bc While deleting: i32 (i32, i32)* %plus An asserting value handle still pointed to this value! I've spent hours looking at this and haven't been able to figure out exactly what the problem is. I've gone from thinking there was something wrong in the C or Ocaml bindings to looking at the innards of the JIT itself. If someone else who understands the Ocaml bindings or the JIT could please take a look, I'd appreciate that. I'm going to keep on debugging and see if I can figure it out. Nick Nick Lewycky wrote: > Author: nicholas > Date: Sun Apr 19 13:32:03 2009 > New Revision: 69531 > > URL: http://llvm.org/viewvc/llvm-project?rev=69531&view=rev > Log: > Use an AssertingVH to detect the case where the Function was deleted but > freeMachineCodeForFunction was never called. > > Modified: > llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp > > Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=69531&r1=69530&r2=69531&view=diff > > ============================================================================== > --- llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp (original) > +++ llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp Sun Apr 19 13:32:03 2009 > @@ -32,6 +32,7 @@ > #include "llvm/Target/TargetOptions.h" > #include "llvm/Support/Debug.h" > #include "llvm/Support/MutexGuard.h" > +#include "llvm/Support/ValueHandle.h" > #include "llvm/System/Disassembler.h" > #include "llvm/System/Memory.h" > #include "llvm/Target/TargetInstrInfo.h" > @@ -57,23 +58,23 @@ > private: > /// FunctionToStubMap - Keep track of the stub created for a particular > /// function so that we can reuse them if necessary. > - std::map FunctionToStubMap; > + std::map, void*> FunctionToStubMap; > > /// StubToFunctionMap - Keep track of the function that each stub > /// corresponds to. > - std::map StubToFunctionMap; > + std::map > StubToFunctionMap; > > /// GlobalToIndirectSymMap - Keep track of the indirect symbol created for a > /// particular GlobalVariable so that we can reuse them if necessary. > std::map GlobalToIndirectSymMap; > > public: > - std::map& getFunctionToStubMap(const MutexGuard& locked) { > + std::map, void*>& getFunctionToStubMap(const MutexGuard& locked) { > assert(locked.holds(TheJIT->lock)); > return FunctionToStubMap; > } > > - std::map& getStubToFunctionMap(const MutexGuard& locked) { > + std::map >& getStubToFunctionMap(const MutexGuard& locked) { > assert(locked.holds(TheJIT->lock)); > return StubToFunctionMap; > } > @@ -275,11 +276,11 @@ > SmallVectorImpl &Ptrs) { > MutexGuard locked(TheJIT->lock); > > - std::map &FM = state.getFunctionToStubMap(locked); > + std::map,void*> &FM =state.getFunctionToStubMap(locked); > std::map &GM = state.getGlobalToIndirectSymMap(locked); > > - for (std::map::iterator i = FM.begin(), e = FM.end(); > - i != e; ++i) { > + for (std::map,void*>::iterator i = FM.begin(), > + e = FM.end(); i != e; ++i) { > Function *F = i->first; > if (F->isDeclaration() && F->hasExternalLinkage()) { > GVs.push_back(i->first); > @@ -296,8 +297,8 @@ > GlobalValue *JITResolver::invalidateStub(void *Stub) { > MutexGuard locked(TheJIT->lock); > > - std::map &FM = state.getFunctionToStubMap(locked); > - std::map &SM = state.getStubToFunctionMap(locked); > + std::map,void*> &FM =state.getFunctionToStubMap(locked); > + std::map > &SM=state.getStubToFunctionMap(locked); > std::map &GM = state.getGlobalToIndirectSymMap(locked); > > // Look up the cheap way first, to see if it's a function stub we are > @@ -348,7 +349,7 @@ > > // The address given to us for the stub may not be exactly right, it might be > // a little bit after the stub. As such, use upper_bound to find it. > - std::map::iterator I = > + std::map >::iterator I = > JR.state.getStubToFunctionMap(locked).upper_bound(Stub); > assert(I != JR.state.getStubToFunctionMap(locked).begin() && > "This is not a known stub!"); > > > _______________________________________________ > 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 Mon Apr 20 00:39:52 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Sun, 19 Apr 2009 22:39:52 -0700 Subject: [llvm-commits] [llvm] r69382 - /llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp In-Reply-To: <1240178728.17299.232.camel@aslstation> References: <200904172042.n3HKgZbA023516@zion.cs.uiuc.edu> <1240178728.17299.232.camel@aslstation> Message-ID: <9F037586-E89B-40D4-A918-A3C2FDABE2F2@apple.com> That makes sense MachineBasicBlock also has a addLiveIn method. Evan On Apr 19, 2009, at 3:05 PM, Anton Korobeynikov wrote: > Hello, Bob > >> Maybe. Can you suggest where it ought to go? It isn't obvious to >> me. > Can this be a method of MachineFunction class? > > -- > With best regards, Anton Korobeynikov. > > Faculty of Mathematics & Mechanics, Saint Petersburg State University. > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From sanjiv.gupta at microchip.com Mon Apr 20 01:05:54 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Mon, 20 Apr 2009 06:05:54 -0000 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> Author: sgupta Date: Mon Apr 20 01:05:54 2009 New Revision: 69574 URL: http://llvm.org/viewvc/llvm-project?rev=69574&view=rev Log: Before trying to introduce/eliminate cast/ext/trunc to make indices type as pointer type, make sure that the pointer size is a valid sequential index type. Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69574&r1=69573&r2=69574&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Apr 20 01:05:54 2009 @@ -10695,7 +10695,12 @@ gep_type_iterator GTI = gep_type_begin(GEP); for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); i != e; ++i, ++GTI) { - if (isa(*GTI)) { + // Before trying to eliminate/introduce cast/ext/trunc to make + // indices as pointer types, make sure that the pointer size + // makes a valid sequential index. + const SequentialType *ST = dyn_cast(*GTI); + Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); + if (ST && ST->indexValid(PtrTypeVal)) { if (CastInst *CI = dyn_cast(*i)) { if (CI->getOpcode() == Instruction::ZExt || CI->getOpcode() == Instruction::SExt) { From baldrick at free.fr Mon Apr 20 02:33:39 2009 From: baldrick at free.fr (Duncan Sands) Date: Mon, 20 Apr 2009 09:33:39 +0200 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> Message-ID: <200904200933.39786.baldrick@free.fr> Hi Sanjiv, > Before trying to introduce/eliminate cast/ext/trunc to make indices type as > pointer type, make sure that the pointer size is a valid sequential index type. what's this about? Got a testcase? Ciao, Duncan. > > Modified: > llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > > Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69574&r1=69573&r2=69574&view=diff > > ============================================================================== > --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Apr 20 01:05:54 2009 > @@ -10695,7 +10695,12 @@ > gep_type_iterator GTI = gep_type_begin(GEP); > for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); > i != e; ++i, ++GTI) { > - if (isa(*GTI)) { > + // Before trying to eliminate/introduce cast/ext/trunc to make > + // indices as pointer types, make sure that the pointer size > + // makes a valid sequential index. > + const SequentialType *ST = dyn_cast(*GTI); > + Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); > + if (ST && ST->indexValid(PtrTypeVal)) { > if (CastInst *CI = dyn_cast(*i)) { > if (CI->getOpcode() == Instruction::ZExt || > CI->getOpcode() == Instruction::SExt) { > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From dgregor at apple.com Mon Apr 20 02:34:18 2009 From: dgregor at apple.com (Douglas Gregor) Date: Mon, 20 Apr 2009 07:34:18 -0000 Subject: [llvm-commits] [llvm] r69583 - in /llvm/trunk: include/llvm/Support/raw_ostream.h lib/Support/raw_ostream.cpp Message-ID: <200904200734.n3K7YIxF012851@zion.cs.uiuc.edu> Author: dgregor Date: Mon Apr 20 02:34:17 2009 New Revision: 69583 URL: http://llvm.org/viewvc/llvm-project?rev=69583&view=rev Log: Make all raw_ostreams support the tell() function. 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=69583&r1=69582&r2=69583&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/raw_ostream.h (original) +++ llvm/trunk/include/llvm/Support/raw_ostream.h Mon Apr 20 02:34:17 2009 @@ -54,6 +54,9 @@ delete [] OutBufStart; } + /// tell - Return the current offset with the file. + uint64_t tell() { return current_pos() + GetNumBytesInBuffer(); } + //===--------------------------------------------------------------------===// // Configuration Interface //===--------------------------------------------------------------------===// @@ -179,6 +182,10 @@ // An out of line virtual method to provide a home for the class vtable. virtual void handle(); + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() = 0; + //===--------------------------------------------------------------------===// // Private Interface //===--------------------------------------------------------------------===// @@ -202,6 +209,11 @@ /// write_impl - See raw_ostream::write_impl. virtual void write_impl(const char *Ptr, unsigned Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() { return pos; } + public: /// raw_fd_ostream - Open the specified file for writing. If an /// error occurs, information about the error is put into ErrorInfo, @@ -271,9 +283,17 @@ /// write_impl - See raw_ostream::write_impl. virtual void write_impl(const char *Ptr, unsigned Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos(); + public: raw_os_ostream(std::ostream &O) : OS(O) {} ~raw_os_ostream(); + + /// tell - Return the current offset with the stream. + uint64_t tell(); }; /// raw_string_ostream - A raw_ostream that writes to an std::string. This is a @@ -283,10 +303,17 @@ /// write_impl - See raw_ostream::write_impl. virtual void write_impl(const char *Ptr, unsigned Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() { return OS.size(); } public: raw_string_ostream(std::string &O) : OS(O) {} ~raw_string_ostream(); + /// tell - Return the current offset with the stream. + uint64_t tell() { return OS.size() + GetNumBytesInBuffer(); } + /// str - Flushes the stream contents to the target string and returns /// the string's reference. std::string& str() { @@ -302,9 +329,16 @@ /// write_impl - See raw_ostream::write_impl. virtual void write_impl(const char *Ptr, unsigned Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos(); public: raw_svector_ostream(SmallVectorImpl &O) : OS(O) {} ~raw_svector_ostream(); + + /// tell - Return the current offset with the stream. + uint64_t tell(); }; } // end llvm namespace Modified: llvm/trunk/lib/Support/raw_ostream.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=69583&r1=69582&r2=69583&view=diff ============================================================================== --- llvm/trunk/lib/Support/raw_ostream.cpp (original) +++ llvm/trunk/lib/Support/raw_ostream.cpp Mon Apr 20 02:34:17 2009 @@ -339,6 +339,12 @@ OS.write(Ptr, Size); } +uint64_t raw_os_ostream::current_pos() { return OS.tellp(); } + +uint64_t raw_os_ostream::tell() { + return (uint64_t)OS.tellp() + GetNumBytesInBuffer(); +} + //===----------------------------------------------------------------------===// // raw_string_ostream //===----------------------------------------------------------------------===// @@ -363,3 +369,8 @@ OS.append(Ptr, Ptr + Size); } +uint64_t raw_svector_ostream::current_pos() { return OS.size(); } + +uint64_t raw_svector_ostream::tell() { + return OS.size() + GetNumBytesInBuffer(); +} From baldrick at free.fr Mon Apr 20 02:37:41 2009 From: baldrick at free.fr (Duncan Sands) Date: Mon, 20 Apr 2009 09:37:41 +0200 Subject: [llvm-commits] =?iso-8859-1?q?=5Bllvm=5D_r69474_-_in_/llvm/trunk?= =?iso-8859-1?q?=3A=09autoconf/configure=2Eactools/llvmc/plugins/Base/Base?= =?iso-8859-1?q?=2Etd=09tools/llvmc/plugins/Base/Base=2Etd=2Ein?= In-Reply-To: References: <200904182055.n3IKtSLI013834@zion.cs.uiuc.edu> <200904191128.57743.baldrick@free.fr> Message-ID: <200904200937.41548.baldrick@free.fr> > > llvm[4]: Building LLVMC configuration library with tblgen > > Parsing .../tools/llvmc/plugins/Base/Release/.dir:1: Unexpected > > input at top level > > Sun Apr 19 11:02:20 CEST 2009 > > ^ > > By the way, do you have llvm-gcc (either configured with > --with-llvmgccdir or somewhere in PATH) on that machine? Yes I do, it's in the path. Ciao, Duncan. From evan.cheng at apple.com Mon Apr 20 03:01:14 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 20 Apr 2009 08:01:14 -0000 Subject: [llvm-commits] [llvm] r69585 - in /llvm/trunk: lib/CodeGen/LiveIntervalAnalysis.cpp lib/CodeGen/RegAllocLinearScan.cpp test/CodeGen/X86/2008-08-05-SpillerBug.ll test/CodeGen/X86/2008-10-16-SpillerBug.ll test/CodeGen/X86/2009-04-20-LinearScanOpt.ll Message-ID: <200904200801.n3K81E8n018383@zion.cs.uiuc.edu> Author: evancheng Date: Mon Apr 20 03:01:12 2009 New Revision: 69585 URL: http://llvm.org/viewvc/llvm-project?rev=69585&view=rev Log: Added a linearscan register allocation optimization. When the register allocator spill an interval with multiple uses in the same basic block, it creates a different virtual register for each of the reloads. e.g. %reg1498 = MOV32rm %reg1024, 1, %reg0, 12, %reg0, Mem:LD(4,4) [sunkaddr39 + 0] %reg1506 = MOV32rm %reg1024, 1, %reg0, 8, %reg0, Mem:LD(4,4) [sunkaddr42 + 0] %reg1486 = MOV32rr %reg1506 %reg1486 = XOR32rr %reg1486, %reg1498, %EFLAGS %reg1510 = MOV32rm %reg1024, 1, %reg0, 4, %reg0, Mem:LD(4,4) [sunkaddr45 + 0] => %reg1498 = MOV32rm %reg2036, 1, %reg0, 12, %reg0, Mem:LD(4,4) [sunkaddr39 + 0] %reg1506 = MOV32rm %reg2037, 1, %reg0, 8, %reg0, Mem:LD(4,4) [sunkaddr42 + 0] %reg1486 = MOV32rr %reg1506 %reg1486 = XOR32rr %reg1486, %reg1498, %EFLAGS %reg1510 = MOV32rm %reg2038, 1, %reg0, 4, %reg0, Mem:LD(4,4) [sunkaddr45 + 0] >From linearscan's point of view, each of reg2036, 2037, and 2038 are separate registers, each is "killed" after a single use. The reloaded register is available and it's often clobbered right away. e.g. In thise case reg1498 is allocated EAX while reg2036 is allocated RAX. This means we end up with multiple reloads from the same stack slot in the same basic block. Now linearscan recognize there are other reloads from same SS in the same BB. So it'll "downgrade" RAX (and its aliases) after reg2036 is allocated until the next reload (reg2037) is done. This greatly increase the likihood reloads from SS are reused. This speeds up sha1 from OpenSSL by 5.8%. It is also an across the board win for SPEC2000 and 2006. Added: llvm/trunk/test/CodeGen/X86/2009-04-20-LinearScanOpt.ll Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp llvm/trunk/test/CodeGen/X86/2008-08-05-SpillerBug.ll llvm/trunk/test/CodeGen/X86/2008-10-16-SpillerBug.ll Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=69585&r1=69584&r2=69585&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Mon Apr 20 03:01:12 2009 @@ -1734,14 +1734,6 @@ } } -namespace { - struct LISorter { - bool operator()(LiveInterval* A, LiveInterval* B) { - return A->beginNumber() < B->beginNumber(); - } - }; -} - std::vector LiveIntervals:: addIntervalsForSpillsFast(const LiveInterval &li, const MachineLoopInfo *loopInfo, @@ -1838,9 +1830,6 @@ RI = mri_->reg_begin(li.reg); } - // Clients expect the new intervals to be returned in sorted order. - std::sort(added.begin(), added.end(), LISorter()); - return added; } Modified: llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp?rev=69585&r1=69584&r2=69585&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Mon Apr 20 03:01:12 2009 @@ -45,6 +45,7 @@ STATISTIC(NumIters , "Number of iterations performed"); STATISTIC(NumBacktracks, "Number of times we had to backtrack"); STATISTIC(NumCoalesce, "Number of copies coalesced"); +STATISTIC(NumDowngrade, "Number of registers downgraded"); static cl::opt NewHeuristic("new-spilling-heuristic", @@ -74,6 +75,19 @@ EquivalenceClasses RelatedRegClasses; DenseMap OneClassForEachPhysReg; + // NextReloadMap - For each register in the map, it maps to the another + // register which is defined by a reload from the same stack slot and + // both reloads are in the same basic block. + DenseMap NextReloadMap; + + // DowngradedRegs - A set of registers which are being "downgraded", i.e. + // un-favored for allocation. + SmallSet DowngradedRegs; + + // DowngradeMap - A map from virtual registers to physical registers being + // downgraded for the virtual registers. + DenseMap DowngradeMap; + MachineFunction* mf_; MachineRegisterInfo* mri_; const TargetMachine* tm_; @@ -151,6 +165,16 @@ /// ones to the active list. void processInactiveIntervals(unsigned CurPoint); + /// hasNextReloadInterval - Return the next liveinterval that's being + /// defined by a reload from the same SS as the specified one. + LiveInterval *hasNextReloadInterval(LiveInterval *cur); + + /// DowngradeRegister - Downgrade a register for allocation. + void DowngradeRegister(LiveInterval *li, unsigned Reg); + + /// UpgradeRegister - Upgrade a register for allocation. + void UpgradeRegister(unsigned Reg); + /// assignRegOrStackSlotAtInterval - assign a register if one /// is available, or spill. void assignRegOrStackSlotAtInterval(LiveInterval* cur); @@ -184,6 +208,10 @@ /// getFreePhysReg - return a free physical register for this virtual /// register interval if we have one, otherwise return 0. unsigned getFreePhysReg(LiveInterval* cur); + unsigned getFreePhysReg(const TargetRegisterClass *RC, + unsigned MaxInactiveCount, + SmallVector &inactiveCounts, + bool SkipDGRegs); /// assignVirt2StackSlot - assigns this virtual register to a /// stack slot. returns the stack slot @@ -211,17 +239,15 @@ X("linearscan-regalloc", "Linear Scan Register Allocator"); void RALinScan::ComputeRelatedRegClasses() { - const TargetRegisterInfo &TRI = *tri_; - // First pass, add all reg classes to the union, and determine at least one // reg class that each register is in. bool HasAliases = false; - for (TargetRegisterInfo::regclass_iterator RCI = TRI.regclass_begin(), - E = TRI.regclass_end(); RCI != E; ++RCI) { + for (TargetRegisterInfo::regclass_iterator RCI = tri_->regclass_begin(), + E = tri_->regclass_end(); RCI != E; ++RCI) { RelatedRegClasses.insert(*RCI); for (TargetRegisterClass::iterator I = (*RCI)->begin(), E = (*RCI)->end(); I != E; ++I) { - HasAliases = HasAliases || *TRI.getAliasSet(*I) != 0; + HasAliases = HasAliases || *tri_->getAliasSet(*I) != 0; const TargetRegisterClass *&PRC = OneClassForEachPhysReg[*I]; if (PRC) { @@ -241,7 +267,7 @@ for (DenseMap::iterator I = OneClassForEachPhysReg.begin(), E = OneClassForEachPhysReg.end(); I != E; ++I) - for (const unsigned *AS = TRI.getAliasSet(I->first); *AS; ++AS) + for (const unsigned *AS = tri_->getAliasSet(I->first); *AS; ++AS) RelatedRegClasses.unionSets(I->second, OneClassForEachPhysReg[*AS]); } @@ -326,6 +352,9 @@ active_.clear(); inactive_.clear(); handled_.clear(); + NextReloadMap.clear(); + DowngradedRegs.clear(); + DowngradeMap.clear(); return true; } @@ -525,6 +554,9 @@ SmallSet Processed; SmallSet SuperAdded; SmallVector Supers; + // Unfavor downgraded registers for spilling. + if (DowngradedRegs.count(reg)) + weight *= 2.0f; Weights[reg] += weight; Processed.insert(reg); for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) { @@ -692,6 +724,43 @@ return (diff / w2) <= 0.05f; // Within 5%. } +LiveInterval *RALinScan::hasNextReloadInterval(LiveInterval *cur) { + DenseMap::iterator I = NextReloadMap.find(cur->reg); + if (I == NextReloadMap.end()) + return 0; + return &li_->getInterval(I->second); +} + +void RALinScan::DowngradeRegister(LiveInterval *li, unsigned Reg) { + bool isNew = DowngradedRegs.insert(Reg); + isNew = isNew; // Silence compiler warning. + assert(isNew && "Multiple reloads holding the same register?"); + DowngradeMap.insert(std::make_pair(li->reg, Reg)); + for (const unsigned *AS = tri_->getAliasSet(Reg); *AS; ++AS) { + isNew = DowngradedRegs.insert(*AS); + isNew = isNew; // Silence compiler warning. + assert(isNew && "Multiple reloads holding the same register?"); + DowngradeMap.insert(std::make_pair(li->reg, *AS)); + } + ++NumDowngrade; +} + +void RALinScan::UpgradeRegister(unsigned Reg) { + if (Reg) { + DowngradedRegs.erase(Reg); + for (const unsigned *AS = tri_->getAliasSet(Reg); *AS; ++AS) + DowngradedRegs.erase(*AS); + } +} + +namespace { + struct LISorter { + bool operator()(LiveInterval* A, LiveInterval* B) { + return A->beginNumber() < B->beginNumber(); + } + }; +} + /// assignRegOrStackSlotAtInterval - assign a register if one is available, or /// spill. void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) @@ -836,6 +905,15 @@ prt_->addRegUse(physReg); active_.push_back(std::make_pair(cur, cur->begin())); handled_.push_back(cur); + + // "Upgrade" the physical register since it has been allocated. + UpgradeRegister(physReg); + if (LiveInterval *NextReloadLI = hasNextReloadInterval(cur)) { + // "Downgrade" physReg to try to keep physReg from being allocated until + // the next reload from the same SS is allocated. + NextReloadLI->preference = physReg; + DowngradeRegister(cur, physReg); + } return; } DOUT << "no free registers\n"; @@ -896,9 +974,10 @@ if (cur->weight == HUGE_VALF || li_->getApproximateInstructionCount(*cur) == 0) { // Spill a physical register around defs and uses. - if (li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_)) + if (li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_)) { + DowngradedRegs.clear(); assignRegOrStackSlotAtInterval(cur); - else { + } else { cerr << "Ran out of registers during register allocation!\n"; exit(1); } @@ -919,7 +998,7 @@ DOUT << tri_->getName(RegsWeights[i].first) << " (" << RegsWeights[i].second << ")\n"); - // if the current has the minimum weight, we need to spill it and + // If the current has the minimum weight, we need to spill it and // add any added intervals back to unhandled, and restart // linearscan. if (cur->weight != HUGE_VALF && cur->weight <= minWeight) { @@ -928,12 +1007,13 @@ SmallVector spillIs; std::vector added = li_->addIntervalsForSpills(*cur, spillIs, loopInfo, *vrm_, SSWeight); + std::sort(added.begin(), added.end(), LISorter()); addStackInterval(cur, ls_, li_, SSWeight, *vrm_); if (added.empty()) return; // Early exit if all spills were folded. - // Merge added with unhandled. Note that we know that - // addIntervalsForSpills returns intervals sorted by their starting + // Merge added with unhandled. Note that we have already sorted + // intervals returned by addIntervalsForSpills by their starting // point. for (unsigned i = 0, e = added.size(); i != e; ++i) unhandled_.push(added[i]); @@ -942,7 +1022,7 @@ ++NumBacktracks; - // push the current interval back to unhandled since we are going + // Push the current interval back to unhandled since we are going // to re-run at least this iteration. Since we didn't modify it it // should go back right in the front of the list unhandled_.push(cur); @@ -1020,10 +1100,15 @@ unhandled_.push(i); } - // It interval has a preference, it must be defined by a copy. Clear the - // preference now since the source interval allocation may have been undone - // as well. - i->preference = 0; + DenseMap::iterator ii = DowngradeMap.find(i->reg); + if (ii == DowngradeMap.end()) + // It interval has a preference, it must be defined by a copy. Clear the + // preference now since the source interval allocation may have been + // undone as well. + i->preference = 0; + else { + UpgradeRegister(ii->second); + } } // Rewind the iterators in the active, inactive, and fixed lists back to the @@ -1032,7 +1117,7 @@ RevertVectorIteratorsTo(inactive_, earliestStart); RevertVectorIteratorsTo(fixed_, earliestStart); - // scan the rest and undo each interval that expired after t and + // Scan the rest and undo each interval that expired after t and // insert it in active (the next iteration of the algorithm will // put it in inactive if required) for (unsigned i = 0, e = handled_.size(); i != e; ++i) { @@ -1046,9 +1131,87 @@ } } - // merge added with unhandled - for (unsigned i = 0, e = added.size(); i != e; ++i) - unhandled_.push(added[i]); + // Merge added with unhandled. + // This also update the NextReloadMap. That is, it adds mapping from a + // register defined by a reload from SS to the next reload from SS in the + // same basic block. + MachineBasicBlock *LastReloadMBB = 0; + LiveInterval *LastReload = 0; + int LastReloadSS = VirtRegMap::NO_STACK_SLOT; + std::sort(added.begin(), added.end(), LISorter()); + for (unsigned i = 0, e = added.size(); i != e; ++i) { + LiveInterval *ReloadLi = added[i]; + if (ReloadLi->weight == HUGE_VALF && + li_->getApproximateInstructionCount(*ReloadLi) == 0) { + unsigned ReloadIdx = ReloadLi->beginNumber(); + MachineBasicBlock *ReloadMBB = li_->getMBBFromIndex(ReloadIdx); + int ReloadSS = vrm_->getStackSlot(ReloadLi->reg); + if (LastReloadMBB == ReloadMBB && LastReloadSS == ReloadSS) { + // Last reload of same SS is in the same MBB. We want to try to + // allocate both reloads the same register and make sure the reg + // isn't clobbered in between if at all possible. + assert(LastReload->beginNumber() < ReloadIdx); + NextReloadMap.insert(std::make_pair(LastReload->reg, ReloadLi->reg)); + } + LastReloadMBB = ReloadMBB; + LastReload = ReloadLi; + LastReloadSS = ReloadSS; + } + unhandled_.push(ReloadLi); + } +} + +unsigned RALinScan::getFreePhysReg(const TargetRegisterClass *RC, + unsigned MaxInactiveCount, + SmallVector &inactiveCounts, + bool SkipDGRegs) { + unsigned FreeReg = 0; + unsigned FreeRegInactiveCount = 0; + + TargetRegisterClass::iterator I = RC->allocation_order_begin(*mf_); + TargetRegisterClass::iterator E = RC->allocation_order_end(*mf_); + assert(I != E && "No allocatable register in this register class!"); + + // Scan for the first available register. + for (; I != E; ++I) { + unsigned Reg = *I; + // Ignore "downgraded" registers. + if (SkipDGRegs && DowngradedRegs.count(Reg)) + continue; + if (prt_->isRegAvail(Reg)) { + FreeReg = Reg; + if (FreeReg < inactiveCounts.size()) + FreeRegInactiveCount = inactiveCounts[FreeReg]; + else + FreeRegInactiveCount = 0; + break; + } + } + + // If there are no free regs, or if this reg has the max inactive count, + // return this register. + if (FreeReg == 0 || FreeRegInactiveCount == MaxInactiveCount) + return FreeReg; + + // Continue scanning the registers, looking for the one with the highest + // inactive count. Alkis found that this reduced register pressure very + // slightly on X86 (in rev 1.94 of this file), though this should probably be + // reevaluated now. + for (; I != E; ++I) { + unsigned Reg = *I; + // Ignore "downgraded" registers. + if (SkipDGRegs && DowngradedRegs.count(Reg)) + continue; + if (prt_->isRegAvail(Reg) && Reg < inactiveCounts.size() && + FreeRegInactiveCount < inactiveCounts[Reg]) { + FreeReg = Reg; + FreeRegInactiveCount = inactiveCounts[Reg]; + if (FreeRegInactiveCount == MaxInactiveCount) + break; // We found the one with the max inactive count. + } + } + + return FreeReg; } /// getFreePhysReg - return a free physical register for this virtual register @@ -1078,9 +1241,6 @@ } } - unsigned FreeReg = 0; - unsigned FreeRegInactiveCount = 0; - // If copy coalescer has assigned a "preferred" register, check if it's // available first. if (cur->preference) { @@ -1094,40 +1254,13 @@ << tri_->getName(cur->preference) << "\n"; } - // Scan for the first available register. - TargetRegisterClass::iterator I = RC->allocation_order_begin(*mf_); - TargetRegisterClass::iterator E = RC->allocation_order_end(*mf_); - assert(I != E && "No allocatable register in this register class!"); - for (; I != E; ++I) - if (prt_->isRegAvail(*I)) { - FreeReg = *I; - if (FreeReg < inactiveCounts.size()) - FreeRegInactiveCount = inactiveCounts[FreeReg]; - else - FreeRegInactiveCount = 0; - break; - } - - // If there are no free regs, or if this reg has the max inactive count, - // return this register. - if (FreeReg == 0 || FreeRegInactiveCount == MaxInactiveCount) return FreeReg; - - // Continue scanning the registers, looking for the one with the highest - // inactive count. Alkis found that this reduced register pressure very - // slightly on X86 (in rev 1.94 of this file), though this should probably be - // reevaluated now. - for (; I != E; ++I) { - unsigned Reg = *I; - if (prt_->isRegAvail(Reg) && Reg < inactiveCounts.size() && - FreeRegInactiveCount < inactiveCounts[Reg]) { - FreeReg = Reg; - FreeRegInactiveCount = inactiveCounts[Reg]; - if (FreeRegInactiveCount == MaxInactiveCount) - break; // We found the one with the max inactive count. - } + if (!DowngradedRegs.empty()) { + unsigned FreeReg = getFreePhysReg(RC, MaxInactiveCount, inactiveCounts, + true); + if (FreeReg) + return FreeReg; } - - return FreeReg; + return getFreePhysReg(RC, MaxInactiveCount, inactiveCounts, false); } FunctionPass* llvm::createLinearScanRegisterAllocator() { Modified: llvm/trunk/test/CodeGen/X86/2008-08-05-SpillerBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-08-05-SpillerBug.ll?rev=69585&r1=69584&r2=69585&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-08-05-SpillerBug.ll (original) +++ llvm/trunk/test/CodeGen/X86/2008-08-05-SpillerBug.ll Mon Apr 20 03:01:12 2009 @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -disable-fp-elim -stats |& grep asm-printer | grep 57 +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -disable-fp-elim -stats |& grep asm-printer | grep 56 ; PR2568 @g_3 = external global i16 ; [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/2008-10-16-SpillerBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-10-16-SpillerBug.ll?rev=69585&r1=69584&r2=69585&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-10-16-SpillerBug.ll (original) +++ llvm/trunk/test/CodeGen/X86/2008-10-16-SpillerBug.ll Mon Apr 20 03:01:12 2009 @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | llc -relocation-model=pic -disable-fp-elim -mtriple=i386-apple-darwin | grep {andl.*7.*ecx} +; RUN: llvm-as < %s | llc -relocation-model=pic -disable-fp-elim -mtriple=i386-apple-darwin | grep {andl.*7.*edx} %struct.XXDActiveTextureTargets = type { i64, i64, i64, i64, i64, i64 } %struct.XXDAlphaTest = type { float, i16, i8, i8 } Added: llvm/trunk/test/CodeGen/X86/2009-04-20-LinearScanOpt.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-04-20-LinearScanOpt.ll?rev=69585&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/2009-04-20-LinearScanOpt.ll (added) +++ llvm/trunk/test/CodeGen/X86/2009-04-20-LinearScanOpt.ll Mon Apr 20 03:01:12 2009 @@ -0,0 +1,121 @@ +; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin10.0 -relocation-model=pic -disable-fp-elim -stats |& grep {Number of registers downgraded} +; rdar://6802189 + +; Test if linearscan is unfavoring registers for allocation to allow more reuse +; of reloads from stack slots. + + %struct.SHA_CTX = type { i32, i32, i32, i32, i32, i32, i32, [16 x i32], i32 } + +define fastcc void @sha1_block_data_order(%struct.SHA_CTX* nocapture %c, i8* %p, i64 %num) nounwind { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %asmtmp511 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 0) nounwind ; [#uses=3] + %asmtmp513 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 0) nounwind ; [#uses=2] + %asmtmp516 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 0) nounwind ; [#uses=1] + %asmtmp517 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 0) nounwind ; [#uses=2] + %0 = xor i32 0, %asmtmp513 ; [#uses=0] + %1 = add i32 0, %asmtmp517 ; [#uses=1] + %2 = add i32 %1, 0 ; [#uses=1] + %3 = add i32 %2, 0 ; [#uses=1] + %asmtmp519 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 0) nounwind ; [#uses=1] + %4 = xor i32 0, %asmtmp511 ; [#uses=1] + %asmtmp520 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 %4) nounwind ; [#uses=2] + %5 = xor i32 0, %asmtmp516 ; [#uses=1] + %6 = xor i32 %5, %asmtmp519 ; [#uses=1] + %7 = add i32 %asmtmp513, -899497514 ; [#uses=1] + %8 = add i32 %7, %asmtmp520 ; [#uses=1] + %9 = add i32 %8, %6 ; [#uses=1] + %10 = add i32 %9, 0 ; [#uses=1] + %asmtmp523 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 0) nounwind ; [#uses=1] + %asmtmp525 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 %3) nounwind ; [#uses=2] + %11 = xor i32 0, %asmtmp525 ; [#uses=1] + %12 = add i32 0, %11 ; [#uses=1] + %13 = add i32 %12, 0 ; [#uses=2] + %asmtmp528 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 %10) nounwind ; [#uses=1] + %14 = xor i32 0, %asmtmp520 ; [#uses=1] + %asmtmp529 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 %14) nounwind ; [#uses=1] + %asmtmp530 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 5, i32 %13) nounwind ; [#uses=1] + %15 = add i32 0, %asmtmp530 ; [#uses=1] + %16 = xor i32 0, %asmtmp523 ; [#uses=1] + %asmtmp532 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 %16) nounwind ; [#uses=2] + %asmtmp533 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 5, i32 %15) nounwind ; [#uses=1] + %17 = xor i32 %13, %asmtmp528 ; [#uses=1] + %18 = xor i32 %17, 0 ; [#uses=1] + %19 = add i32 %asmtmp525, -899497514 ; [#uses=1] + %20 = add i32 %19, %asmtmp532 ; [#uses=1] + %21 = add i32 %20, %18 ; [#uses=1] + %22 = add i32 %21, %asmtmp533 ; [#uses=1] + %23 = xor i32 0, %asmtmp511 ; [#uses=1] + %24 = xor i32 %23, 0 ; [#uses=1] + %asmtmp535 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 %24) nounwind ; [#uses=3] + %25 = add i32 0, %asmtmp535 ; [#uses=1] + %26 = add i32 %25, 0 ; [#uses=1] + %27 = add i32 %26, 0 ; [#uses=1] + %28 = xor i32 0, %asmtmp529 ; [#uses=0] + %29 = xor i32 %22, 0 ; [#uses=1] + %30 = xor i32 %29, 0 ; [#uses=1] + %31 = add i32 0, %30 ; [#uses=1] + %32 = add i32 %31, 0 ; [#uses=3] + %asmtmp541 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 0) nounwind ; [#uses=2] + %asmtmp542 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 5, i32 %32) nounwind ; [#uses=1] + %33 = add i32 0, %asmtmp541 ; [#uses=1] + %34 = add i32 %33, 0 ; [#uses=1] + %35 = add i32 %34, %asmtmp542 ; [#uses=1] + %asmtmp543 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 %27) nounwind ; [#uses=2] + %36 = xor i32 0, %asmtmp535 ; [#uses=0] + %37 = xor i32 %32, 0 ; [#uses=1] + %38 = xor i32 %37, %asmtmp543 ; [#uses=1] + %39 = add i32 0, %38 ; [#uses=1] + %40 = add i32 %39, 0 ; [#uses=2] + %asmtmp546 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 %32) nounwind ; [#uses=1] + %asmtmp547 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 0) nounwind ; [#uses=2] + %41 = add i32 0, -899497514 ; [#uses=1] + %42 = add i32 %41, %asmtmp547 ; [#uses=1] + %43 = add i32 %42, 0 ; [#uses=1] + %44 = add i32 %43, 0 ; [#uses=3] + %asmtmp549 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 %35) nounwind ; [#uses=2] + %45 = xor i32 0, %asmtmp541 ; [#uses=1] + %asmtmp550 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 %45) nounwind ; [#uses=2] + %asmtmp551 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 5, i32 %44) nounwind ; [#uses=1] + %46 = xor i32 %40, %asmtmp546 ; [#uses=1] + %47 = xor i32 %46, %asmtmp549 ; [#uses=1] + %48 = add i32 %asmtmp543, -899497514 ; [#uses=1] + %49 = add i32 %48, %asmtmp550 ; [#uses=1] + %50 = add i32 %49, %47 ; [#uses=1] + %51 = add i32 %50, %asmtmp551 ; [#uses=1] + %asmtmp552 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 %40) nounwind ; [#uses=2] + %52 = xor i32 %44, %asmtmp549 ; [#uses=1] + %53 = xor i32 %52, %asmtmp552 ; [#uses=1] + %54 = add i32 0, %53 ; [#uses=1] + %55 = add i32 %54, 0 ; [#uses=2] + %asmtmp555 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 %44) nounwind ; [#uses=2] + %56 = xor i32 0, %asmtmp532 ; [#uses=1] + %57 = xor i32 %56, %asmtmp547 ; [#uses=1] + %asmtmp556 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 %57) nounwind ; [#uses=1] + %58 = add i32 0, %asmtmp556 ; [#uses=1] + %59 = add i32 %58, 0 ; [#uses=1] + %60 = add i32 %59, 0 ; [#uses=1] + %asmtmp558 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 %51) nounwind ; [#uses=1] + %61 = xor i32 %asmtmp517, %asmtmp511 ; [#uses=1] + %62 = xor i32 %61, %asmtmp535 ; [#uses=1] + %63 = xor i32 %62, %asmtmp550 ; [#uses=1] + %asmtmp559 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 1, i32 %63) nounwind ; [#uses=1] + %64 = xor i32 %55, %asmtmp555 ; [#uses=1] + %65 = xor i32 %64, %asmtmp558 ; [#uses=1] + %asmtmp561 = tail call i32 asm "roll $1,$0", "=r,I,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i32 30, i32 %55) nounwind ; [#uses=1] + %66 = add i32 %asmtmp552, -899497514 ; [#uses=1] + %67 = add i32 %66, %65 ; [#uses=1] + %68 = add i32 %67, %asmtmp559 ; [#uses=1] + %69 = add i32 %68, 0 ; [#uses=1] + %70 = add i32 %69, 0 ; [#uses=1] + store i32 %70, i32* null, align 4 + %71 = add i32 0, %60 ; [#uses=1] + store i32 %71, i32* null, align 4 + %72 = add i32 0, %asmtmp561 ; [#uses=1] + store i32 %72, i32* null, align 4 + %73 = add i32 0, %asmtmp555 ; [#uses=1] + store i32 %73, i32* null, align 4 + br label %bb +} From sanjiv.gupta at microchip.com Mon Apr 20 04:30:44 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Mon, 20 Apr 2009 15:00:44 +0530 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <200904200933.39786.baldrick@free.fr> References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> <200904200933.39786.baldrick@free.fr> Message-ID: <49EC40C4.1020301@microchip.com> Duncan Sands wrote: > Hi Sanjiv, > > >> Before trying to introduce/eliminate cast/ext/trunc to make indices type as >> pointer type, make sure that the pointer size is a valid sequential index type. >> > > what's this about? Got a testcase? > > Ciao, > > Duncan. > > Hi Duncan, Here it is http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-April/021785.html - Sanjiv >> Modified: >> llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> >> Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69574&r1=69573&r2=69574&view=diff >> >> ============================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) >> +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Apr 20 01:05:54 2009 >> @@ -10695,7 +10695,12 @@ >> gep_type_iterator GTI = gep_type_begin(GEP); >> for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); >> i != e; ++i, ++GTI) { >> - if (isa(*GTI)) { >> + // Before trying to eliminate/introduce cast/ext/trunc to make >> + // indices as pointer types, make sure that the pointer size >> + // makes a valid sequential index. >> + const SequentialType *ST = dyn_cast(*GTI); >> + Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); >> + if (ST && ST->indexValid(PtrTypeVal)) { >> if (CastInst *CI = dyn_cast(*i)) { >> if (CI->getOpcode() == Instruction::ZExt || >> CI->getOpcode() == Instruction::SExt) { >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> >> > > From gohman at apple.com Mon Apr 20 10:31:12 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 20 Apr 2009 08:31:12 -0700 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> Message-ID: <83B4B74F-3F9C-4A66-8447-40970738F0AD@apple.com> Hello, Are you planning to resubmit r58505? It was reverted in r58547 with a message indicating that it would be resubmitted. That patch would appear to make this r69574 unnecessary. Dan On Apr 19, 2009, at 11:05 PM, Sanjiv Gupta wrote: > Author: sgupta > Date: Mon Apr 20 01:05:54 2009 > New Revision: 69574 > > URL: http://llvm.org/viewvc/llvm-project?rev=69574&view=rev > Log: > Before trying to introduce/eliminate cast/ext/trunc to make indices > type as > pointer type, make sure that the pointer size is a valid sequential > index type. > > Modified: > llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > > Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69574&r1=69573&r2=69574&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > (original) > +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon > Apr 20 01:05:54 2009 > @@ -10695,7 +10695,12 @@ > gep_type_iterator GTI = gep_type_begin(GEP); > for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); > i != e; ++i, ++GTI) { > - if (isa(*GTI)) { > + // Before trying to eliminate/introduce cast/ext/trunc to make > + // indices as pointer types, make sure that the pointer size > + // makes a valid sequential index. > + const SequentialType *ST = dyn_cast(*GTI); > + Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); > + if (ST && ST->indexValid(PtrTypeVal)) { > if (CastInst *CI = dyn_cast(*i)) { > if (CI->getOpcode() == Instruction::ZExt || > CI->getOpcode() == Instruction::SExt) { > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From gohman at apple.com Mon Apr 20 10:55:38 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 20 Apr 2009 15:55:38 -0000 Subject: [llvm-commits] [llvm] r69596 - /llvm/trunk/lib/VMCore/Type.cpp Message-ID: <200904201555.n3KFtcHO003643@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 10:55:38 2009 New Revision: 69596 URL: http://llvm.org/viewvc/llvm-project?rev=69596&view=rev Log: Implement operator<<(raw_ostream &OS, const Type &T). Modified: llvm/trunk/lib/VMCore/Type.cpp Modified: llvm/trunk/lib/VMCore/Type.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=69596&r1=69595&r2=69596&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Type.cpp (original) +++ llvm/trunk/lib/VMCore/Type.cpp Mon Apr 20 10:55:38 2009 @@ -1428,4 +1428,9 @@ T.print(OS); return OS; } + +raw_ostream &operator<<(raw_ostream &OS, const Type &T) { + T.print(OS); + return OS; +} } From baldrick at free.fr Mon Apr 20 11:03:21 2009 From: baldrick at free.fr (Duncan Sands) Date: Mon, 20 Apr 2009 16:03:21 -0000 Subject: [llvm-commits] [llvm] r69597 - /llvm/trunk/include/llvm/Transforms/Utils/InlineCost.h Message-ID: <200904201603.n3KG3LP1003871@zion.cs.uiuc.edu> Author: baldrick Date: Mon Apr 20 11:03:21 2009 New Revision: 69597 URL: http://llvm.org/viewvc/llvm-project?rev=69597&view=rev Log: These bitfields were being miscompiled on some 64 bit platforms when building with optimization. So replace them by a hand-coded implementation. This fixes PR3822. Modified: llvm/trunk/include/llvm/Transforms/Utils/InlineCost.h Modified: llvm/trunk/include/llvm/Transforms/Utils/InlineCost.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/InlineCost.h?rev=69597&r1=69596&r2=69597&view=diff ============================================================================== --- llvm/trunk/include/llvm/Transforms/Utils/InlineCost.h (original) +++ llvm/trunk/include/llvm/Transforms/Utils/InlineCost.h Mon Apr 20 11:03:21 2009 @@ -16,6 +16,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include +#include #include #include @@ -37,26 +38,41 @@ Never }; - int Cost : 30; - unsigned Type : 2; + // This is a do-it-yourself implementation of + // int Cost : 30; + // unsigned Type : 2; + // We used to use bitfields, but they were sometimes miscompiled (PR3822). + enum { TYPE_BITS = 2 }; + enum { COST_BITS = unsigned(sizeof(unsigned)) * CHAR_BIT - TYPE_BITS }; + unsigned TypedCost; // int Cost : COST_BITS; unsigned Type : TYPE_BITS; - InlineCost(int C, int T) : Cost(C), Type(T) { - assert(Cost == C && "Cost exceeds InlineCost precision"); + Kind getType() const { + return Kind(TypedCost >> COST_BITS); + } + + int getCost() const { + // Sign-extend the bottom COST_BITS bits. + return (int(TypedCost << TYPE_BITS)) >> TYPE_BITS; + } + + InlineCost(int C, int T) { + TypedCost = (unsigned(C << TYPE_BITS) >> TYPE_BITS) | (T << COST_BITS); + assert(getCost() == C && "Cost exceeds InlineCost precision"); } public: static InlineCost get(int Cost) { return InlineCost(Cost, Value); } static InlineCost getAlways() { return InlineCost(0, Always); } - static InlineCost getNever() { return InlineCost(0, Never); } + static InlineCost getNever() { return InlineCost(0, Never); } - bool isVariable() const { return Type == Value; } - bool isAlways() const { return Type == Always; } - bool isNever() const { return Type == Never; } + bool isVariable() const { return getType() == Value; } + bool isAlways() const { return getType() == Always; } + bool isNever() const { return getType() == Never; } /// getValue() - Return a "variable" inline cost's amount. It is /// an error to call this on an "always" or "never" InlineCost. - int getValue() const { - assert(Type == Value && "Invalid access of InlineCost"); - return Cost; + int getValue() const { + assert(getType() == Value && "Invalid access of InlineCost"); + return getCost(); } }; From gohman at apple.com Mon Apr 20 11:10:33 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 20 Apr 2009 16:10:33 -0000 Subject: [llvm-commits] [llvm] r69598 - /llvm/trunk/lib/VMCore/AsmWriter.cpp Message-ID: <200904201610.n3KGAXmY004289@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 11:10:33 2009 New Revision: 69598 URL: http://llvm.org/viewvc/llvm-project?rev=69598&view=rev Log: Don't discard an AssemblyAnnotationWriter when writing GlobalValues, which include Functions, where it can be quite useful to use an AssemblyAnnotationWriter. Modified: llvm/trunk/lib/VMCore/AsmWriter.cpp Modified: llvm/trunk/lib/VMCore/AsmWriter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AsmWriter.cpp?rev=69598&r1=69597&r2=69598&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/AsmWriter.cpp (original) +++ llvm/trunk/lib/VMCore/AsmWriter.cpp Mon Apr 20 11:10:33 2009 @@ -1833,7 +1833,7 @@ W.write(BB); } else if (const GlobalValue *GV = dyn_cast(this)) { SlotTracker SlotTable(GV->getParent()); - AssemblyWriter W(OS, SlotTable, GV->getParent(), 0); + AssemblyWriter W(OS, SlotTable, GV->getParent(), AAW); W.write(GV); } else if (const Constant *C = dyn_cast(this)) { TypePrinting TypePrinter; From sanjiv.gupta at microchip.com Mon Apr 20 11:16:11 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Mon, 20 Apr 2009 21:46:11 +0530 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <83B4B74F-3F9C-4A66-8447-40970738F0AD@apple.com> References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> <83B4B74F-3F9C-4A66-8447-40970738F0AD@apple.com> Message-ID: <49EC9FCB.7040501@microchip.com> Dan Gohman wrote: > Hello, > > Are you planning to resubmit r58505? It was reverted in r58547 with > a message indicating that it would be resubmitted. That patch would > appear to make this r69574 unnecessary. > > Dan > > Right. Even after that this change will still hold good just in case if a pointer size doesn't make valid index. Chris had suggested that 58505 alone is not enough as the bc encoding uses 1 bit to encode i32/i64 for index types. He had suggested that we should be able to write i16 type indexes and should be able to get back them by the command seq below. $ llvm-as < test.ll | llvm-dis | llvm-as | llvm-dis When I tried this with 58505, it worked. So the only additional thing is that we probably need to do the changes in the documentation. Let me know if this understanding is incorrect. Better you can get me a test case. - Sanjiv > On Apr 19, 2009, at 11:05 PM, Sanjiv Gupta wrote: > > >> Author: sgupta >> Date: Mon Apr 20 01:05:54 2009 >> New Revision: 69574 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=69574&view=rev >> Log: >> Before trying to introduce/eliminate cast/ext/trunc to make indices >> type as >> pointer type, make sure that the pointer size is a valid sequential >> index type. >> >> Modified: >> llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> >> Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69574&r1=69573&r2=69574&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> ====================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> (original) >> +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon >> Apr 20 01:05:54 2009 >> @@ -10695,7 +10695,12 @@ >> gep_type_iterator GTI = gep_type_begin(GEP); >> for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); >> i != e; ++i, ++GTI) { >> - if (isa(*GTI)) { >> + // Before trying to eliminate/introduce cast/ext/trunc to make >> + // indices as pointer types, make sure that the pointer size >> + // makes a valid sequential index. >> + const SequentialType *ST = dyn_cast(*GTI); >> + Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); >> + if (ST && ST->indexValid(PtrTypeVal)) { >> if (CastInst *CI = dyn_cast(*i)) { >> if (CI->getOpcode() == Instruction::ZExt || >> CI->getOpcode() == Instruction::SExt) { >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From gohman at apple.com Mon Apr 20 11:19:02 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 20 Apr 2009 16:19:02 -0000 Subject: [llvm-commits] [llvm] r69599 - /llvm/trunk/tools/llvm-extract/llvm-extract.cpp Message-ID: <200904201619.n3KGJ2t3004737@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 11:19:02 2009 New Revision: 69599 URL: http://llvm.org/viewvc/llvm-project?rev=69599&view=rev Log: Use .empty() instead of .size(). Modified: llvm/trunk/tools/llvm-extract/llvm-extract.cpp Modified: llvm/trunk/tools/llvm-extract/llvm-extract.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-extract/llvm-extract.cpp?rev=69599&r1=69598&r2=69599&view=diff ============================================================================== --- llvm/trunk/tools/llvm-extract/llvm-extract.cpp (original) +++ llvm/trunk/tools/llvm-extract/llvm-extract.cpp Mon Apr 20 11:19:02 2009 @@ -81,11 +81,11 @@ } // Figure out which function we should extract - GlobalVariable *G = ExtractGlobal.size() ? + GlobalVariable *G = !ExtractGlobal.empty() ? M.get()->getNamedGlobal(ExtractGlobal) : 0; // Figure out which function we should extract - if (!ExtractFunc.size() && !ExtractGlobal.size()) ExtractFunc = "main"; + if (ExtractFunc.empty() && ExtractGlobal.empty()) ExtractFunc = "main"; Function *F = M.get()->getFunction(ExtractFunc); if (F == 0 && G == 0) { From gohman at apple.com Mon Apr 20 11:26:25 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 20 Apr 2009 16:26:25 -0000 Subject: [llvm-commits] [llvm] r69602 - /llvm/trunk/lib/VMCore/PrintModulePass.cpp Message-ID: <200904201626.n3KGQPkr005031@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 11:26:25 2009 New Revision: 69602 URL: http://llvm.org/viewvc/llvm-project?rev=69602&view=rev Log: It's not necessary for PrintModulePass to flush the output streams now that errs() is properly non-buffered. Modified: llvm/trunk/lib/VMCore/PrintModulePass.cpp Modified: llvm/trunk/lib/VMCore/PrintModulePass.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/PrintModulePass.cpp?rev=69602&r1=69601&r2=69602&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/PrintModulePass.cpp (original) +++ llvm/trunk/lib/VMCore/PrintModulePass.cpp Mon Apr 20 11:26:25 2009 @@ -38,7 +38,6 @@ bool runOnModule(Module &M) { (*Out) << M; - Out->flush(); return false; } @@ -67,7 +66,6 @@ // bool runOnFunction(Function &F) { (*Out) << Banner << static_cast(F); - Out->flush(); return false; } From sanjiv.gupta at microchip.com Mon Apr 20 11:59:44 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Mon, 20 Apr 2009 16:59:44 -0000 Subject: [llvm-commits] [llvm] r69605 - in /llvm/trunk: lib/Target/PIC16/PIC16AsmPrinter.cpp lib/Target/PIC16/PIC16AsmPrinter.h tools/Makefile Message-ID: <200904201659.n3KGxjGa006363@zion.cs.uiuc.edu> Author: sgupta Date: Mon Apr 20 11:59:35 2009 New Revision: 69605 URL: http://llvm.org/viewvc/llvm-project?rev=69605&view=rev Log: Emit the auto variables of a function into a different section than parameters. Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h llvm/trunk/tools/Makefile Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp?rev=69605&r1=69604&r2=69605&view=diff ============================================================================== --- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp (original) +++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Mon Apr 20 11:59:35 2009 @@ -67,7 +67,7 @@ else { // External Symbol is generated for temp data. Temp data in in // fdata..# section. - NewBank = "fdata." + CurrentFnName +".#"; + NewBank = "fpdata." + CurrentFnName +".#"; } // Operand after global address or external symbol should be banksel. // Value 1 for this operand means we need to generate banksel else do not @@ -117,8 +117,8 @@ // Emit the frame address of the function at the beginning of code. O << CurrentFnName << ":\n"; - O << " retlw low(" << CurrentFnName << ".frame)\n"; - O << " retlw high(" << CurrentFnName << ".frame)\n"; + O << " retlw low(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n"; + O << " retlw high(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n"; // Print out code for the function. @@ -178,14 +178,22 @@ O << (int)MO.getImm(); return; - case MachineOperand::MO_GlobalAddress: - O << Mang->getValueName(MO.getGlobal()); + case MachineOperand::MO_GlobalAddress: { + std::string Name = Mang->getValueName(MO.getGlobal()); + if (isLocalName(Name)) + O << FunctionLabelBegin << Mang->getValueName(MO.getGlobal()); + else + O << Mang->getValueName(MO.getGlobal()); break; - - case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); + } + case MachineOperand::MO_ExternalSymbol: { + std::string Name = MO.getSymbolName(); + if (Name.find("__intrinsics.") != std::string::npos) + O << MO.getSymbolName(); + else + O << FunctionLabelBegin << MO.getSymbolName(); break; - + } case MachineOperand::MO_MachineBasicBlock: printBasicBlockLabel(MO.getMBB()); return; @@ -234,13 +242,13 @@ if (I->isDeclaration()) { O << "\textern " <hasExternalLinkage()) { O << "\tglobal " << Name << "\n"; - O << "\tglobal " << Name << ".retval\n"; - O << "\tglobal " << Name << ".args\n"; + O << "\tglobal " << FunctionLabelBegin << Name << ".retval\n"; + O << "\tglobal " << FunctionLabelBegin<< Name << ".args\n"; } } @@ -371,15 +379,16 @@ unsigned FrameSize = 0; // Emit the data section name. O << "\n"; - std::string SectionName = "fdata." + CurrentFnName + ".# " + "UDATA"; + std::string SectionName = "fpdata." + CurrentFnName + ".# " + "UDATA_OVR"; - const Section *fDataSection = TAI->getNamedSection(SectionName.c_str(), - SectionFlags::Writeable); - SwitchToSection(fDataSection); + const Section *fPDataSection = TAI->getNamedSection(SectionName.c_str(), + SectionFlags::Writeable); + SwitchToSection(fPDataSection); // Emit function frame label - O << CurrentFnName << ".frame:\n"; + char ch; + O << FunctionLabelBegin << CurrentFnName << ".frame:\n"; const Type *RetType = F->getReturnType(); unsigned RetSize = 0; @@ -388,9 +397,10 @@ //Emit function return value space if(RetSize > 0) - O << CurrentFnName << ".retval RES " << RetSize << "\n"; + O << FunctionLabelBegin << CurrentFnName << ".retval RES " << RetSize + << "\n"; else - O << CurrentFnName << ".retval:\n"; + O << FunctionLabelBegin << CurrentFnName << ".retval:\n"; // Emit variable to hold the space for function arguments unsigned ArgSize = 0; @@ -399,12 +409,22 @@ const Type *Ty = argi->getType(); ArgSize += TD->getTypePaddedSize(Ty); } - O << CurrentFnName << ".args RES " << ArgSize << "\n"; + O << FunctionLabelBegin << CurrentFnName << ".args RES " << ArgSize + << "\n"; // Emit temporary space int TempSize = PTLI->GetTmpSize(); if (TempSize > 0 ) - O << CurrentFnName << ".tmp RES " << TempSize <<"\n"; + O << FunctionLabelBegin << CurrentFnName << ".tmp RES " << TempSize + <<"\n"; + + // Emit the section name for local variables. + O << "\n"; + std::string SecNameLocals = "fadata." + CurrentFnName + ".# " + "UDATA_OVR"; + + const Section *fADataSection = TAI->getNamedSection(SecNameLocals.c_str(), + SectionFlags::Writeable); + SwitchToSection(fADataSection); // Emit the function variables. @@ -424,13 +444,13 @@ if (! isLocalToFunc(FuncName, VarName)) continue; - I->setSection("fdata." + CurrentFnName + ".#"); + I->setSection("fadata." + CurrentFnName + ".#"); Constant *C = I->getInitializer(); const Type *Ty = C->getType(); unsigned Size = TD->getTypePaddedSize(Ty); FrameSize += Size; // Emit memory reserve directive. - O << VarName << " RES " << Size << "\n"; + O << FunctionLabelBegin << VarName << " RES " << Size << "\n"; } } Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h?rev=69605&r1=69604&r2=69605&view=diff ============================================================================== --- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h (original) +++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h Mon Apr 20 11:59:35 2009 @@ -28,6 +28,7 @@ const TargetAsmInfo *T, bool F, bool V) : AsmPrinter(O, TM, T, F, V) { CurBank = ""; + FunctionLabelBegin = '@'; IsRomData = false; PTLI = TM.getTargetLowering(); } @@ -55,6 +56,7 @@ PIC16TargetLowering *PTLI; std::string CurBank; bool IsRomData; + char FunctionLabelBegin; }; } // end of namespace Modified: llvm/trunk/tools/Makefile URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/Makefile?rev=69605&r1=69604&r2=69605&view=diff ============================================================================== --- llvm/trunk/tools/Makefile (original) +++ llvm/trunk/tools/Makefile Mon Apr 20 11:59:35 2009 @@ -20,7 +20,7 @@ llc llvm-ranlib llvm-ar llvm-nm \ llvm-ld llvm-prof llvm-link \ lli gccas gccld llvm-extract llvm-db \ - bugpoint llvm-bcanalyzer llvm-stub llvmc + bugpoint llvm-bcanalyzer llvm-stub llvmc clang include $(LEVEL)/Makefile.config From anton at korobeynikov.info Mon Apr 20 12:10:15 2009 From: anton at korobeynikov.info (Anton Korobeynikov) Date: Mon, 20 Apr 2009 21:10:15 +0400 Subject: [llvm-commits] [llvm] r69605 - in /llvm/trunk: lib/Target/PIC16/PIC16AsmPrinter.cpp lib/Target/PIC16/PIC16AsmPrinter.h tools/Makefile In-Reply-To: <200904201659.n3KGxjGa006363@zion.cs.uiuc.edu> References: <200904201659.n3KGxjGa006363@zion.cs.uiuc.edu> Message-ID: Hello, Sanjiv > ============================================================================== > --- llvm/trunk/tools/Makefile (original) > +++ llvm/trunk/tools/Makefile Mon Apr 20 11:59:35 2009 > @@ -20,7 +20,7 @@ > ? ? ? ? ? ? ? ? ?llc llvm-ranlib llvm-ar llvm-nm \ > ? ? ? ? ? ? ? ? ?llvm-ld llvm-prof llvm-link \ > ? ? ? ? ? ? ? ? ?lli gccas gccld llvm-extract llvm-db \ > - ? ? ? ? ? ? ? ? bugpoint llvm-bcanalyzer llvm-stub llvmc > + ? ? ? ? ? ? ? ? bugpoint llvm-bcanalyzer llvm-stub llvmc clang Did you really want to commit this hunk? -- With best regards, Anton Korobeynikov Faculty of Mathematics and Mechanics, Saint Petersburg State University From evan.cheng at apple.com Mon Apr 20 12:23:49 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 20 Apr 2009 17:23:49 -0000 Subject: [llvm-commits] [llvm] r69606 - /llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Message-ID: <200904201723.n3KHNo3r007061@zion.cs.uiuc.edu> Author: evancheng Date: Mon Apr 20 12:23:48 2009 New Revision: 69606 URL: http://llvm.org/viewvc/llvm-project?rev=69606&view=rev Log: - Remove an arbitrary spill weight tweak that should not have been there. - Find more reloads from SS. Modified: llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Modified: llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp?rev=69606&r1=69605&r2=69606&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Mon Apr 20 12:23:48 2009 @@ -554,9 +554,6 @@ SmallSet Processed; SmallSet SuperAdded; SmallVector Supers; - // Unfavor downgraded registers for spilling. - if (DowngradedRegs.count(reg)) - weight *= 2.0f; Weights[reg] += weight; Processed.insert(reg); for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) { @@ -1015,8 +1012,32 @@ // Merge added with unhandled. Note that we have already sorted // intervals returned by addIntervalsForSpills by their starting // point. - for (unsigned i = 0, e = added.size(); i != e; ++i) - unhandled_.push(added[i]); + // This also update the NextReloadMap. That is, it adds mapping from a + // register defined by a reload from SS to the next reload from SS in the + // same basic block. + MachineBasicBlock *LastReloadMBB = 0; + LiveInterval *LastReload = 0; + int LastReloadSS = VirtRegMap::NO_STACK_SLOT; + for (unsigned i = 0, e = added.size(); i != e; ++i) { + LiveInterval *ReloadLi = added[i]; + if (ReloadLi->weight == HUGE_VALF && + li_->getApproximateInstructionCount(*ReloadLi) == 0) { + unsigned ReloadIdx = ReloadLi->beginNumber(); + MachineBasicBlock *ReloadMBB = li_->getMBBFromIndex(ReloadIdx); + int ReloadSS = vrm_->getStackSlot(ReloadLi->reg); + if (LastReloadMBB == ReloadMBB && LastReloadSS == ReloadSS) { + // Last reload of same SS is in the same MBB. We want to try to + // allocate both reloads the same register and make sure the reg + // isn't clobbered in between if at all possible. + assert(LastReload->beginNumber() < ReloadIdx); + NextReloadMap.insert(std::make_pair(LastReload->reg, ReloadLi->reg)); + } + LastReloadMBB = ReloadMBB; + LastReload = ReloadLi; + LastReloadSS = ReloadSS; + } + unhandled_.push(ReloadLi); + } return; } From bob.wilson at apple.com Mon Apr 20 12:27:09 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Mon, 20 Apr 2009 17:27:09 -0000 Subject: [llvm-commits] [llvm] r69607 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAGNodes.h lib/CodeGen/SelectionDAG/DAGCombiner.cpp lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200904201727.n3KHR9WK007196@zion.cs.uiuc.edu> Author: bwilson Date: Mon Apr 20 12:27:09 2009 New Revision: 69607 URL: http://llvm.org/viewvc/llvm-project?rev=69607&view=rev Log: Revise my previous change 68996 as suggested by Duncan. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=69607&r1=69606&r2=69607&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Mon Apr 20 12:27:09 2009 @@ -288,13 +288,12 @@ // value as an integer 0/1 value. FGETSIGN, - /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector - /// with the specified, possibly variable, elements. The number of elements - /// is required to be a power of two. The types of the operands must - /// all be the same. They must match the vector element type, except if an - /// integer element type is not legal for the target, the operands may - /// be promoted to a legal type, in which case the operands are implicitly - /// truncated to the vector element types. + /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the + /// specified, possibly variable, elements. The number of elements is + /// required to be a power of two. The types of the operands must all be + /// the same and must match the vector element type, except that integer + /// types are allowed to be larger than the element type, in which case + /// the operands are implicitly truncated. BUILD_VECTOR, /// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=69607&r1=69606&r2=69607&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Apr 20 12:27:09 2009 @@ -3811,12 +3811,8 @@ SDValue Op = BV->getOperand(i); // If the vector element type is not legal, the BUILD_VECTOR operands // are promoted and implicitly truncated. Make that explicit here. - if (Op.getValueType() != SrcEltVT) { - if (Op.getOpcode() == ISD::UNDEF) - Op = DAG.getUNDEF(SrcEltVT); - else - Op = DAG.getNode(ISD::TRUNCATE, BV->getDebugLoc(), SrcEltVT, Op); - } + if (Op.getValueType() != SrcEltVT) + Op = DAG.getNode(ISD::TRUNCATE, BV->getDebugLoc(), SrcEltVT, Op); Ops.push_back(DAG.getNode(ISD::BIT_CONVERT, BV->getDebugLoc(), DstEltVT, Op)); AddToWorkList(Ops.back().getNode()); Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp?rev=69607&r1=69606&r2=69607&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp Mon Apr 20 12:27:09 2009 @@ -808,9 +808,8 @@ "Type of inserted value narrower than vector element type!"); SmallVector NewOps; - for (unsigned i = 0; i < NumElts; ++i) { + for (unsigned i = 0; i < NumElts; ++i) NewOps.push_back(GetPromotedInteger(N->getOperand(i))); - } return DAG.UpdateNodeOperands(SDValue(N, 0), &NewOps[0], NumElts); } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=69607&r1=69606&r2=69607&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Apr 20 12:27:09 2009 @@ -2556,7 +2556,8 @@ if (Elt.getValueType() != VT) { // If the vector element type is not legal, the BUILD_VECTOR operands // are promoted and implicitly truncated. Make that explicit here. - assert(Elt.getValueType() == TLI.getTypeToTransformTo(VT) && + assert(VT.isInteger() && Elt.getValueType().isInteger() && + VT.bitsLE(Elt.getValueType()) && "Bad type for BUILD_VECTOR operand"); Elt = getNode(ISD::TRUNCATE, DL, VT, Elt); } From tonic at nondot.org Mon Apr 20 12:48:16 2009 From: tonic at nondot.org (Tanya Lattner) Date: Mon, 20 Apr 2009 17:48:16 -0000 Subject: [llvm-commits] [llvm] r69610 - /llvm/trunk/tools/Makefile Message-ID: <200904201748.n3KHmGvD008003@zion.cs.uiuc.edu> Author: tbrethou Date: Mon Apr 20 12:48:16 2009 New Revision: 69610 URL: http://llvm.org/viewvc/llvm-project?rev=69610&view=rev Log: Remove clang since its conditionally there already. Modified: llvm/trunk/tools/Makefile Modified: llvm/trunk/tools/Makefile URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/Makefile?rev=69610&r1=69609&r2=69610&view=diff ============================================================================== --- llvm/trunk/tools/Makefile (original) +++ llvm/trunk/tools/Makefile Mon Apr 20 12:48:16 2009 @@ -20,7 +20,7 @@ llc llvm-ranlib llvm-ar llvm-nm \ llvm-ld llvm-prof llvm-link \ lli gccas gccld llvm-extract llvm-db \ - bugpoint llvm-bcanalyzer llvm-stub llvmc clang + bugpoint llvm-bcanalyzer llvm-stub llvmc include $(LEVEL)/Makefile.config From dpatel at apple.com Mon Apr 20 13:07:22 2009 From: dpatel at apple.com (Devang Patel) Date: Mon, 20 Apr 2009 18:07:22 -0000 Subject: [llvm-commits] [llvm] r69613 - /llvm/trunk/lib/Target/CBackend/CTargetMachine.h Message-ID: <200904201807.n3KI7Mbi008621@zion.cs.uiuc.edu> Author: dpatel Date: Mon Apr 20 13:07:22 2009 New Revision: 69613 URL: http://llvm.org/viewvc/llvm-project?rev=69613&view=rev Log: Match C backend only if it explicitly requested. Modified: llvm/trunk/lib/Target/CBackend/CTargetMachine.h Modified: llvm/trunk/lib/Target/CBackend/CTargetMachine.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CBackend/CTargetMachine.h?rev=69613&r1=69612&r2=69613&view=diff ============================================================================== --- llvm/trunk/lib/Target/CBackend/CTargetMachine.h (original) +++ llvm/trunk/lib/Target/CBackend/CTargetMachine.h Mon Apr 20 13:07:22 2009 @@ -29,8 +29,9 @@ virtual bool addPassesToEmitWholeFile(PassManager &PM, raw_ostream &Out, CodeGenFileType FileType, bool Fast); - // This class always works, but shouldn't be the default in most cases. - static unsigned getModuleMatchQuality(const Module &M) { return 1; } + // This class always works, but must be requested explicitly on + // llc command line. + static unsigned getModuleMatchQuality(const Module &M) { return 0; } virtual const TargetData *getTargetData() const { return &DataLayout; } }; From bob.wilson at apple.com Mon Apr 20 13:36:58 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Mon, 20 Apr 2009 18:36:58 -0000 Subject: [llvm-commits] [llvm] r69615 - in /llvm/trunk: include/llvm/CodeGen/MachineFunction.h lib/CodeGen/MachineFunction.cpp lib/Target/ARM/ARMISelLowering.cpp lib/Target/X86/X86ISelLowering.cpp Message-ID: <200904201836.n3KIaw4i009552@zion.cs.uiuc.edu> Author: bwilson Date: Mon Apr 20 13:36:57 2009 New Revision: 69615 URL: http://llvm.org/viewvc/llvm-project?rev=69615&view=rev Log: Move duplicated AddLiveIn function from X86 and ARM backends to be a method in the MachineFunction class, renaming it to addLiveIn for consistency with the same method in MachineBasicBlock. Thanks for Anton for suggesting this. Modified: llvm/trunk/include/llvm/CodeGen/MachineFunction.h llvm/trunk/lib/CodeGen/MachineFunction.cpp llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Modified: llvm/trunk/include/llvm/CodeGen/MachineFunction.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFunction.h?rev=69615&r1=69614&r2=69615&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineFunction.h (original) +++ llvm/trunk/include/llvm/CodeGen/MachineFunction.h Mon Apr 20 13:36:57 2009 @@ -33,6 +33,7 @@ class MachineConstantPool; class MachineJumpTableInfo; class TargetMachine; +class TargetRegisterClass; template <> struct ilist_traits @@ -238,6 +239,10 @@ typedef std::reverse_iterator const_reverse_iterator; typedef std::reverse_iterator reverse_iterator; + /// addLiveIn - Add the specified physical register as a live-in value and + /// create a corresponding virtual register for it. + unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC); + //===--------------------------------------------------------------------===// // BasicBlock accessor functions. // Modified: llvm/trunk/lib/CodeGen/MachineFunction.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineFunction.cpp?rev=69615&r1=69614&r2=69615&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineFunction.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineFunction.cpp Mon Apr 20 13:36:57 2009 @@ -385,6 +385,16 @@ return *mc; } +/// addLiveIn - Add the specified physical register as a live-in value and +/// create a corresponding virtual register for it. +unsigned MachineFunction::addLiveIn(unsigned PReg, + const TargetRegisterClass *RC) { + assert(RC->contains(PReg) && "Not the correct regclass!"); + unsigned VReg = getRegInfo().createVirtualRegister(RC); + getRegInfo().addLiveIn(PReg, VReg); + return VReg; +} + /// getOrCreateDebugLocID - Look up the DebugLocTuple index with the given /// source file, line, and column. If none currently exists, create a new /// DebugLocTuple, and insert it into the DebugIdMap. Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=69615&r1=69614&r2=69615&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Apr 20 13:36:57 2009 @@ -1053,17 +1053,6 @@ return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0); } -/// AddLiveIn - This helper function adds the specified physical register to the -/// MachineFunction as a live-in value. It also creates a corresponding virtual -/// register for it. -static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, - const TargetRegisterClass *RC) { - assert(RC->contains(PReg) && "Not the correct regclass!"); - unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); - MF.getRegInfo().addLiveIn(PReg, VReg); - return VReg; -} - SDValue ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) { MachineFunction &MF = DAG.getMachineFunction(); @@ -1101,7 +1090,7 @@ assert(0 && "RegVT not supported by FORMAL_ARGUMENTS Lowering"); // Transform the arguments stored in physical registers into virtual ones. - unsigned Reg = AddLiveIn(MF, VA.getLocReg(), RC); + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, RegVT); // f64 is passed in i32 pairs and must be combined. @@ -1118,7 +1107,7 @@ SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); ArgValue2 = DAG.getLoad(MVT::i32, dl, Root, FIN, NULL, 0); } else { - Reg = AddLiveIn(MF, VA.getLocReg(), RC); + Reg = MF.addLiveIn(VA.getLocReg(), RC); ArgValue2 = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32); } @@ -1195,7 +1184,7 @@ else RC = ARM::GPRRegisterClass; - unsigned VReg = AddLiveIn(MF, GPRArgRegs[NumGPRs], RC); + unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC); SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); MemOps.push_back(Store); Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=69615&r1=69614&r2=69615&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Apr 20 13:36:57 2009 @@ -1147,17 +1147,6 @@ // For info on fast calling convention see Fast Calling Convention (tail call) // implementation LowerX86_32FastCCCallTo. -/// AddLiveIn - This helper function adds the specified physical register to the -/// MachineFunction as a live in value. It also creates a corresponding virtual -/// register for it. -static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, - const TargetRegisterClass *RC) { - assert(RC->contains(PReg) && "Not the correct regclass!"); - unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); - MF.getRegInfo().addLiveIn(PReg, VReg); - return VReg; -} - /// CallIsStructReturn - Determines whether a CALL node uses struct return /// semantics. static bool CallIsStructReturn(CallSDNode *TheCall) { @@ -1356,7 +1345,7 @@ assert(0 && "Unknown argument type!"); } - unsigned Reg = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC); + unsigned Reg = DAG.getMachineFunction().addLiveIn(VA.getLocReg(), RC); SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, RegVT); // If this is an 8 or 16-bit value, it is really passed promoted to 32 @@ -1472,8 +1461,8 @@ SDValue FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), RSFIN, DAG.getIntPtrConstant(VarArgsGPOffset)); for (; NumIntRegs != TotalNumIntRegs; ++NumIntRegs) { - unsigned VReg = AddLiveIn(MF, GPR64ArgRegs[NumIntRegs], - X86::GR64RegisterClass); + unsigned VReg = MF.addLiveIn(GPR64ArgRegs[NumIntRegs], + X86::GR64RegisterClass); SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::i64); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, @@ -1487,8 +1476,8 @@ FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), RSFIN, DAG.getIntPtrConstant(VarArgsFPOffset)); for (; NumXMMRegs != TotalNumXMMRegs; ++NumXMMRegs) { - unsigned VReg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs], - X86::VR128RegisterClass); + unsigned VReg = MF.addLiveIn(XMMArgRegs[NumXMMRegs], + X86::VR128RegisterClass); SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::v4f32); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, From daniel at zuster.org Mon Apr 20 15:34:38 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Mon, 20 Apr 2009 20:34:38 -0000 Subject: [llvm-commits] [llvm] r69624 - /llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Message-ID: <200904202034.n3KKYdlr013548@zion.cs.uiuc.edu> Author: ddunbar Date: Mon Apr 20 15:34:38 2009 New Revision: 69624 URL: http://llvm.org/viewvc/llvm-project?rev=69624&view=rev Log: Remove unused variable. Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp?rev=69624&r1=69623&r2=69624&view=diff ============================================================================== --- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp (original) +++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Mon Apr 20 15:34:38 2009 @@ -387,7 +387,6 @@ // Emit function frame label - char ch; O << FunctionLabelBegin << CurrentFnName << ".frame:\n"; const Type *RetType = F->getReturnType(); From daniel at zuster.org Mon Apr 20 15:50:13 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Mon, 20 Apr 2009 20:50:13 -0000 Subject: [llvm-commits] [llvm] r69626 - in /llvm/trunk/lib/System/Unix: Memory.inc Path.inc Program.inc Unix.h Message-ID: <200904202050.n3KKoDHX014086@zion.cs.uiuc.edu> Author: ddunbar Date: Mon Apr 20 15:50:13 2009 New Revision: 69626 URL: http://llvm.org/viewvc/llvm-project?rev=69626&view=rev Log: Make Unix.h:MakeErrMsg separate the prefix and errno string, so we get: clang: error: unable to make temporary file: /etc/cc: can't make unique filename: Permission denied instead of clang: error: unable to make temporary file: /etc/cc: can't make unique filenamePermission denied for example. Also, audited the uses of MakeErrMsg to make the prefix strings consistent (not end with newline/punctuation/space/": "). Modified: llvm/trunk/lib/System/Unix/Memory.inc llvm/trunk/lib/System/Unix/Path.inc llvm/trunk/lib/System/Unix/Program.inc llvm/trunk/lib/System/Unix/Unix.h Modified: llvm/trunk/lib/System/Unix/Memory.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Unix/Memory.inc?rev=69626&r1=69625&r2=69626&view=diff ============================================================================== --- llvm/trunk/lib/System/Unix/Memory.inc (original) +++ llvm/trunk/lib/System/Unix/Memory.inc Mon Apr 20 15:50:13 2009 @@ -76,7 +76,7 @@ (vm_size_t)(pageSize*NumPages), 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); if (KERN_SUCCESS != kr) { - MakeErrMsg(ErrMsg, "vm_protect max RX failed\n"); + MakeErrMsg(ErrMsg, "vm_protect max RX failed"); return sys::MemoryBlock(); } @@ -84,7 +84,7 @@ (vm_size_t)(pageSize*NumPages), 0, VM_PROT_READ | VM_PROT_WRITE); if (KERN_SUCCESS != kr) { - MakeErrMsg(ErrMsg, "vm_protect RW failed\n"); + MakeErrMsg(ErrMsg, "vm_protect RW failed"); return sys::MemoryBlock(); } #endif Modified: llvm/trunk/lib/System/Unix/Path.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Unix/Path.inc?rev=69626&r1=69625&r2=69626&view=diff ============================================================================== --- llvm/trunk/lib/System/Unix/Path.inc (original) +++ llvm/trunk/lib/System/Unix/Path.inc Mon Apr 20 15:50:13 2009 @@ -748,7 +748,7 @@ Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) { if (0 != ::rename(path.c_str(), newName.c_str())) return MakeErrMsg(ErrMsg, std::string("can't rename '") + path + "' as '" + - newName.toString() + "' "); + newName.toString() + "'"); return false; } @@ -786,7 +786,7 @@ if (errno != EINTR && errno != EAGAIN) { ::close(inFile); ::close(outFile); - return MakeErrMsg(ErrMsg, Src.toString()+": can't read source file: "); + return MakeErrMsg(ErrMsg, Src.toString()+": can't read source file"); } } else { char *BufPtr = Buffer; @@ -797,7 +797,7 @@ ::close(inFile); ::close(outFile); return MakeErrMsg(ErrMsg, Dest.toString() + - ": can't write destination file: "); + ": can't write destination file"); } } else { Amt -= AmtWritten; Modified: llvm/trunk/lib/System/Unix/Program.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Unix/Program.inc?rev=69626&r1=69625&r2=69626&view=diff ============================================================================== --- llvm/trunk/lib/System/Unix/Program.inc (original) +++ llvm/trunk/lib/System/Unix/Program.inc Mon Apr 20 15:50:13 2009 @@ -99,7 +99,7 @@ int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); if (InFD == -1) { MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for " - + (FD == 0 ? "input" : "output") + "!\n"); + + (FD == 0 ? "input" : "output")); return true; } Modified: llvm/trunk/lib/System/Unix/Unix.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Unix/Unix.h?rev=69626&r1=69625&r2=69626&view=diff ============================================================================== --- llvm/trunk/lib/System/Unix/Unix.h (original) +++ llvm/trunk/lib/System/Unix/Unix.h Mon Apr 20 15:50:13 2009 @@ -70,6 +70,9 @@ /// string and the Unix error number given by \p errnum. If errnum is -1, the /// default then the value of errno is used. /// @brief Make an error message +/// +/// If the error number can be converted to a string, it will be +/// separated from prefix by ": ". static inline bool MakeErrMsg( std::string* ErrMsg, const std::string& prefix, int errnum = -1) { if (!ErrMsg) @@ -94,7 +97,7 @@ // but, oh well, just use a generic message sprintf(buffer, "Error #%d", errnum); #endif - *ErrMsg = prefix + buffer; + *ErrMsg = prefix + ": " + buffer; return true; } From evan.cheng at apple.com Mon Apr 20 17:16:40 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 20 Apr 2009 22:16:40 -0000 Subject: [llvm-commits] [llvm] r69630 - in /llvm/trunk: Makefile.rules utils/buildit/build_llvm Message-ID: <200904202216.n3KMGeSf017278@zion.cs.uiuc.edu> Author: evancheng Date: Mon Apr 20 17:16:40 2009 New Revision: 69630 URL: http://llvm.org/viewvc/llvm-project?rev=69630&view=rev Log: One Mac OS X, just build with -O3 but without -fstrict-aliasing (which is kinda broken). Modified: llvm/trunk/Makefile.rules llvm/trunk/utils/buildit/build_llvm Modified: llvm/trunk/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/Makefile.rules?rev=69630&r1=69629&r2=69630&view=diff ============================================================================== --- llvm/trunk/Makefile.rules (original) +++ llvm/trunk/Makefile.rules Mon Apr 20 17:16:40 2009 @@ -229,12 +229,12 @@ CPP.Defines := # OPTIMIZE_OPTION - The optimization level option we want to build LLVM with # this can be overridden on the make command line. -# Avoid -O3 on Darwin, there are unresolved issues with -# -fstrict-aliasing and ipa-type-escape radr://6756684 -ifeq ($(OS), $(filter $(OS), MingW Darwin)) - OPTIMIZE_OPTION := -O2 -else - OPTIMIZE_OPTION := -O3 +ifndef OPTIMIZE_OPTION + ifneq ($(OS),MingW) + OPTIMIZE_OPTION := -O3 + else + OPTIMIZE_OPTION := -O2 + endif endif ifeq ($(ENABLE_OPTIMIZED),1) @@ -247,9 +247,11 @@ endif # Darwin requires -fstrict-aliasing to be explicitly enabled. - ifeq ($(OS),Darwin) - EXTRA_OPTIONS += -fstrict-aliasing -Wstrict-aliasing - endif + # Avoid -O3 on Darwin for now, there are unresolved issues with + # -fstrict-aliasing and ipa-type-escape radr://6756684 + #ifeq ($(OS),Darwin) + # EXTRA_OPTIONS += -fstrict-aliasing -Wstrict-aliasing + #endif CXX.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) C.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) LD.Flags += $(OPTIMIZE_OPTION) Modified: llvm/trunk/utils/buildit/build_llvm URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/buildit/build_llvm?rev=69630&r1=69629&r2=69630&view=diff ============================================================================== --- llvm/trunk/utils/buildit/build_llvm (original) +++ llvm/trunk/utils/buildit/build_llvm Mon Apr 20 17:16:40 2009 @@ -161,7 +161,7 @@ make $LOCAL_MAKEFLAGS $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$TARGETS" \ LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \ LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \ - OPTIMIZE_OPTION='-O2' VERBOSE=1 install + OPTIMIZE_OPTION='-O3' VERBOSE=1 install if ! test $? == 0 ; then echo "error: LLVM 'make install' failed!" From dalej at apple.com Mon Apr 20 17:19:34 2009 From: dalej at apple.com (Dale Johannesen) Date: Mon, 20 Apr 2009 22:19:34 -0000 Subject: [llvm-commits] [llvm] r69631 - /llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp Message-ID: <200904202219.n3KMJYsf017409@zion.cs.uiuc.edu> Author: johannes Date: Mon Apr 20 17:19:33 2009 New Revision: 69631 URL: http://llvm.org/viewvc/llvm-project?rev=69631&view=rev Log: Adjust loop size estimate for full unrolling; GEP's don't usually become instructions. Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp?rev=69631&r1=69630&r2=69631&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp Mon Apr 20 17:19:33 2009 @@ -89,6 +89,8 @@ // Ignore instructions only used by the loop terminator. } else if (isa(I)) { // Ignore debug instructions + } else if (isa(I) && I->hasOneUse()) { + // Ignore GEP as they generally are subsumed into a load or store. } else if (isa(I)) { // Estimate size overhead introduced by call instructions which // is higher than other instructions. Here 3 and 10 are magic From evan.cheng at apple.com Mon Apr 20 17:25:15 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 20 Apr 2009 15:25:15 -0700 Subject: [llvm-commits] [llvm] r69631 - /llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp In-Reply-To: <200904202219.n3KMJYsf017409@zion.cs.uiuc.edu> References: <200904202219.n3KMJYsf017409@zion.cs.uiuc.edu> Message-ID: On Apr 20, 2009, at 3:19 PM, Dale Johannesen wrote: > Author: johannes > Date: Mon Apr 20 17:19:33 2009 > New Revision: 69631 > > URL: http://llvm.org/viewvc/llvm-project?rev=69631&view=rev > Log: > Adjust loop size estimate for full unrolling; > GEP's don't usually become instructions. Well... That's not entirely true. Each GEP can also become a several instructions. Is there a test case to demonstrate the merit of this change? Evan > > > > Modified: > llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp > > Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp?rev=69631&r1=69630&r2=69631&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp Mon Apr 20 > 17:19:33 2009 > @@ -89,6 +89,8 @@ > // Ignore instructions only used by the loop terminator. > } else if (isa(I)) { > // Ignore debug instructions > + } else if (isa(I) && I->hasOneUse()) { > + // Ignore GEP as they generally are subsumed into a load or > store. > } else if (isa(I)) { > // Estimate size overhead introduced by call instructions > which > // is higher than other instructions. Here 3 and 10 are magic > > > _______________________________________________ > 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 Mon Apr 20 17:32:50 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 20 Apr 2009 15:32:50 -0700 Subject: [llvm-commits] [llvm] r69631 - /llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp In-Reply-To: References: <200904202219.n3KMJYsf017409@zion.cs.uiuc.edu> Message-ID: On Apr 20, 2009, at 3:25 PM, Evan Cheng wrote: > > On Apr 20, 2009, at 3:19 PM, Dale Johannesen wrote: > >> Author: johannes >> Date: Mon Apr 20 17:19:33 2009 >> New Revision: 69631 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=69631&view=rev >> Log: >> Adjust loop size estimate for full unrolling; >> GEP's don't usually become instructions. > > Well... That's not entirely true. Each GEP can also become a several > instructions. Is there a test case to demonstrate the merit of this > change? > How about changing it to what InlineCost.cpp does? } else if (const GetElementPtrInst *GEPI = dyn_cast(II)) { // If a GEP has all constant indices, it will probably be folded with // a load/store. bool AllConstant = true; for (unsigned i = 1, e = GEPI->getNumOperands(); i != e; ++i) if (!isa(GEPI->getOperand(i))) { AllConstant = false; break; } if (AllConstant) continue; Evan > Evan > >> >> >> >> Modified: >> llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp >> >> Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp?rev=69631&r1=69630&r2=69631&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> = >> ===================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp (original) >> +++ llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp Mon Apr 20 >> 17:19:33 2009 >> @@ -89,6 +89,8 @@ >> // Ignore instructions only used by the loop terminator. >> } else if (isa(I)) { >> // Ignore debug instructions >> + } else if (isa(I) && I->hasOneUse()) { >> + // Ignore GEP as they generally are subsumed into a load or >> store. >> } else if (isa(I)) { >> // Estimate size overhead introduced by call instructions >> which >> // is higher than other instructions. Here 3 and 10 are magic >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From dalej at apple.com Mon Apr 20 17:41:27 2009 From: dalej at apple.com (Dale Johannesen) Date: Mon, 20 Apr 2009 15:41:27 -0700 Subject: [llvm-commits] [llvm] r69631 - /llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp In-Reply-To: References: <200904202219.n3KMJYsf017409@zion.cs.uiuc.edu> Message-ID: On Apr 20, 2009, at 3:25 PMPDT, Evan Cheng wrote: > On Apr 20, 2009, at 3:19 PM, Dale Johannesen wrote: >> Author: johannes >> Date: Mon Apr 20 17:19:33 2009 >> New Revision: 69631 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=69631&view=rev >> Log: >> Adjust loop size estimate for full unrolling; >> GEP's don't usually become instructions. > > Well... That's not entirely true. Each GEP can also become a several > instructions. Is there a test case to demonstrate the merit of this > change? > > Evan It causes several loops in openssl(aes) to become completely unrolled, recovering 1/3 to 1/4 of the difference between llvm-gcc and gcc. All this is used for is determining whether to completely unroll loops, so it won't matter often. But I have no problem doing this some other way, e.g. increasing the threshold, if you prefer. Why don't we see how it does overnight? > How about changing it to what InlineCost.cpp does? > > } else if (const GetElementPtrInst *GEPI = > dyn_cast(II)) { > // If a GEP has all constant indices, it will probably be > folded with > // a load/store. > bool AllConstant = true; > for (unsigned i = 1, e = GEPI->getNumOperands(); i != e; ++i) > if (!isa(GEPI->getOperand(i))) { > AllConstant = false; > break; > } > if (AllConstant) continue; The subscripts involved are not constant (they're based off the induction variable, as you would expect in a loop), so that won't work. >> Modified: >> llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp >> >> Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp?rev=69631&r1=69630&r2=69631&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> = >> ===================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp (original) >> +++ llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp Mon Apr 20 >> 17:19:33 2009 >> @@ -89,6 +89,8 @@ >> // Ignore instructions only used by the loop terminator. >> } else if (isa(I)) { >> // Ignore debug instructions >> + } else if (isa(I) && I->hasOneUse()) { >> + // Ignore GEP as they generally are subsumed into a load or >> store. >> } else if (isa(I)) { >> // Estimate size overhead introduced by call instructions >> which >> // is higher than other instructions. Here 3 and 10 are magic >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From mrs at apple.com Mon Apr 20 17:46:15 2009 From: mrs at apple.com (Mike Stump) Date: Mon, 20 Apr 2009 15:46:15 -0700 Subject: [llvm-commits] [llvm] r69630 - in /llvm/trunk: Makefile.rules utils/buildit/build_llvm In-Reply-To: <200904202216.n3KMGeSf017278@zion.cs.uiuc.edu> References: <200904202216.n3KMGeSf017278@zion.cs.uiuc.edu> Message-ID: On Apr 20, 2009, at 3:16 PM, Evan Cheng wrote: > One Mac OS X, just build with -O3 but without -fstrict-aliasing > (which is kinda broken). > + # Avoid -O3 on Darwin for now, there are unresolved issues with > + # -fstrict-aliasing and ipa-type-escape radr://6756684 > + #ifeq ($(OS),Darwin) > + # EXTRA_OPTIONS += -fstrict-aliasing -Wstrict-aliasing > + #endif This avoids -fstrict-aliasing -Wstrict-aliasing, but not -O3! From evan.cheng at apple.com Mon Apr 20 17:50:05 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 20 Apr 2009 22:50:05 -0000 Subject: [llvm-commits] [llvm] r69633 - /llvm/trunk/Makefile.rules Message-ID: <200904202250.n3KMo67f018561@zion.cs.uiuc.edu> Author: evancheng Date: Mon Apr 20 17:49:59 2009 New Revision: 69633 URL: http://llvm.org/viewvc/llvm-project?rev=69633&view=rev Log: No, we are not avoiding -O3, just -fstrict-aliasing. Modified: llvm/trunk/Makefile.rules Modified: llvm/trunk/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/Makefile.rules?rev=69633&r1=69632&r2=69633&view=diff ============================================================================== --- llvm/trunk/Makefile.rules (original) +++ llvm/trunk/Makefile.rules Mon Apr 20 17:49:59 2009 @@ -247,8 +247,8 @@ endif # Darwin requires -fstrict-aliasing to be explicitly enabled. - # Avoid -O3 on Darwin for now, there are unresolved issues with - # -fstrict-aliasing and ipa-type-escape radr://6756684 + # Avoid -fstrict-aliasing on Darwin for now, there are unresolved issues + # with -fstrict-aliasing and ipa-type-escape radr://6756684 #ifeq ($(OS),Darwin) # EXTRA_OPTIONS += -fstrict-aliasing -Wstrict-aliasing #endif From gohman at apple.com Mon Apr 20 17:51:44 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 20 Apr 2009 22:51:44 -0000 Subject: [llvm-commits] [llvm] r69634 - /llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200904202251.n3KMpi2M018615@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 17:51:43 2009 New Revision: 69634 URL: http://llvm.org/viewvc/llvm-project?rev=69634&view=rev Log: Simplify this code. getConstant knows how to make broadcasted vector constants. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=69634&r1=69633&r2=69634&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Apr 20 17:51:43 2009 @@ -839,16 +839,9 @@ /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). /// SDValue SelectionDAG::getNOT(DebugLoc DL, SDValue Val, MVT VT) { - SDValue NegOne; - if (VT.isVector()) { - MVT EltVT = VT.getVectorElementType(); - SDValue NegOneElt = - getConstant(APInt::getAllOnesValue(EltVT.getSizeInBits()), EltVT); - std::vector NegOnes(VT.getVectorNumElements(), NegOneElt); - NegOne = getNode(ISD::BUILD_VECTOR, DL, VT, &NegOnes[0], NegOnes.size()); - } else { - NegOne = getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT); - } + MVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT; + SDValue NegOne = + getConstant(APInt::getAllOnesValue(EltVT.getSizeInBits()), VT); return getNode(ISD::XOR, DL, VT, Val, NegOne); } From gohman at apple.com Mon Apr 20 17:54:35 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 20 Apr 2009 22:54:35 -0000 Subject: [llvm-commits] [llvm] r69635 - in /llvm/trunk/lib: CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp Target/X86/X86InstrInfo.cpp Message-ID: <200904202254.n3KMsadT018796@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 17:54:34 2009 New Revision: 69635 URL: http://llvm.org/viewvc/llvm-project?rev=69635&view=rev Log: Make X86's copyRegToReg able to handle copies to and from subclasses. This makes the extra copyRegToReg calls in ScheduleDAGSDNodesEmit.cpp unnecessary. Derived from a patch by Jakob Stoklund Olesen. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp?rev=69635&r1=69634&r2=69635&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp Mon Apr 20 17:54:34 2009 @@ -131,12 +131,6 @@ VRBase = MRI.createVirtualRegister(DstRC); bool Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg, DstRC, SrcRC); - // If the target didn't handle the copy with different register - // classes and the destination is a subset of the source, - // try a normal same-RC copy. - if (!Emitted && DstRC->hasSuperClass(SrcRC)) - Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg, - SrcRC, SrcRC); assert(Emitted && "Unable to issue a copy instruction!\n"); } @@ -273,12 +267,6 @@ unsigned NewVReg = MRI.createVirtualRegister(DstRC); bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg, DstRC, SrcRC); - // If the target didn't handle the copy with different register - // classes and the destination is a subset of the source, - // try a normal same-RC copy. - if (!Emitted && DstRC->hasSuperClass(SrcRC)) - Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg, - SrcRC, SrcRC); assert(Emitted && "Unable to issue a copy instruction!\n"); VReg = NewVReg; } @@ -480,12 +468,6 @@ unsigned NewVReg = MRI.createVirtualRegister(DstRC); bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg, DstRC, SrcRC); - // If the target didn't handle the copy with different register - // classes and the destination is a subset of the source, - // try a normal same-RC copy. - if (!Emitted && SrcRC->hasSubClass(DstRC)) - Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg, - SrcRC, SrcRC); assert(Emitted && "Unable to issue a copy instruction for a COPY_TO_REGCLASS node!\n"); @@ -610,13 +592,6 @@ bool Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg, DstTRC, SrcTRC); - // If the target didn't handle the copy with different register - // classes and the destination is a subset of the source, - // try a normal same-RC copy. - if (!Emitted && DstTRC->hasSubClass(SrcTRC)) - Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg, - DstTRC, DstTRC); - assert(Emitted && "Unable to issue a copy instruction!\n"); break; } Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=69635&r1=69634&r2=69635&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Mon Apr 20 17:54:34 2009 @@ -1656,15 +1656,24 @@ DebugLoc DL = DebugLoc::getUnknownLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc(); - if (DestRC == SrcRC) { + // Determine if DstRC and SrcRC have a common superclass in common. + const TargetRegisterClass *CommonRC = DestRC; + if (DestRC == SrcRC) + /* Source and destination have the same register class. */; + else if (CommonRC->hasSuperClass(SrcRC)) + CommonRC = SrcRC; + else if (!DestRC->hasSubClass(SrcRC)) + CommonRC = 0; + + if (CommonRC) { unsigned Opc; - if (DestRC == &X86::GR64RegClass) { + if (CommonRC == &X86::GR64RegClass) { Opc = X86::MOV64rr; - } else if (DestRC == &X86::GR32RegClass) { + } else if (CommonRC == &X86::GR32RegClass) { Opc = X86::MOV32rr; - } else if (DestRC == &X86::GR16RegClass) { + } else if (CommonRC == &X86::GR16RegClass) { Opc = X86::MOV16rr; - } else if (DestRC == &X86::GR8RegClass) { + } else if (CommonRC == &X86::GR8RegClass) { // Copying two or from a physical H register on x86-64 requires a NOREX // move. Otherwise use a normal move. if ((isHReg(DestReg) || isHReg(SrcReg)) && @@ -1672,35 +1681,35 @@ Opc = X86::MOV8rr_NOREX; else Opc = X86::MOV8rr; - } else if (DestRC == &X86::GR64_RegClass) { + } else if (CommonRC == &X86::GR64_RegClass) { Opc = X86::MOV64rr; - } else if (DestRC == &X86::GR32_RegClass) { + } else if (CommonRC == &X86::GR32_RegClass) { Opc = X86::MOV32rr; - } else if (DestRC == &X86::GR16_RegClass) { + } else if (CommonRC == &X86::GR16_RegClass) { Opc = X86::MOV16rr; - } else if (DestRC == &X86::GR8_RegClass) { + } else if (CommonRC == &X86::GR8_RegClass) { Opc = X86::MOV8rr; - } else if (DestRC == &X86::GR64_NOREXRegClass) { + } else if (CommonRC == &X86::GR64_NOREXRegClass) { Opc = X86::MOV64rr; - } else if (DestRC == &X86::GR32_NOREXRegClass) { + } else if (CommonRC == &X86::GR32_NOREXRegClass) { Opc = X86::MOV32rr; - } else if (DestRC == &X86::GR16_NOREXRegClass) { + } else if (CommonRC == &X86::GR16_NOREXRegClass) { Opc = X86::MOV16rr; - } else if (DestRC == &X86::GR8_NOREXRegClass) { + } else if (CommonRC == &X86::GR8_NOREXRegClass) { Opc = X86::MOV8rr; - } else if (DestRC == &X86::RFP32RegClass) { + } else if (CommonRC == &X86::RFP32RegClass) { Opc = X86::MOV_Fp3232; - } else if (DestRC == &X86::RFP64RegClass || DestRC == &X86::RSTRegClass) { + } else if (CommonRC == &X86::RFP64RegClass || CommonRC == &X86::RSTRegClass) { Opc = X86::MOV_Fp6464; - } else if (DestRC == &X86::RFP80RegClass) { + } else if (CommonRC == &X86::RFP80RegClass) { Opc = X86::MOV_Fp8080; - } else if (DestRC == &X86::FR32RegClass) { + } else if (CommonRC == &X86::FR32RegClass) { Opc = X86::FsMOVAPSrr; - } else if (DestRC == &X86::FR64RegClass) { + } else if (CommonRC == &X86::FR64RegClass) { Opc = X86::FsMOVAPDrr; - } else if (DestRC == &X86::VR128RegClass) { + } else if (CommonRC == &X86::VR128RegClass) { Opc = X86::MOVAPSrr; - } else if (DestRC == &X86::VR64RegClass) { + } else if (CommonRC == &X86::VR64RegClass) { Opc = X86::MMX_MOVQ64rr; } else { return false; From evan.cheng at apple.com Mon Apr 20 17:55:56 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 20 Apr 2009 15:55:56 -0700 Subject: [llvm-commits] [llvm] r69631 - /llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp In-Reply-To: References: <200904202219.n3KMJYsf017409@zion.cs.uiuc.edu> Message-ID: <2C433A0A-C1C1-4BD9-97CB-8B55F355A29F@apple.com> On Apr 20, 2009, at 3:41 PM, Dale Johannesen wrote: > > On Apr 20, 2009, at 3:25 PMPDT, Evan Cheng wrote: >> On Apr 20, 2009, at 3:19 PM, Dale Johannesen wrote: >>> Author: johannes >>> Date: Mon Apr 20 17:19:33 2009 >>> New Revision: 69631 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=69631&view=rev >>> Log: >>> Adjust loop size estimate for full unrolling; >>> GEP's don't usually become instructions. >> >> Well... That's not entirely true. Each GEP can also become a several >> instructions. Is there a test case to demonstrate the merit of this >> change? >> >> Evan > > It causes several loops in openssl(aes) to become completely unrolled, > recovering 1/3 to 1/4 of the difference between llvm-gcc and gcc. > All this is used for is determining whether to completely unroll > loops, so it won't matter often. But I have no problem doing this > some other way, e.g. increasing the threshold, if you prefer. Why > don't we see how it does overnight? Have you had a chance to run it through some large tests, e.g. SPEC? I do expect this need to be revisited. Still, a test case is nice otherwise I have no clue what this really change. > > >> How about changing it to what InlineCost.cpp does? >> >> } else if (const GetElementPtrInst *GEPI = >> dyn_cast(II)) { >> // If a GEP has all constant indices, it will probably be >> folded with >> // a load/store. >> bool AllConstant = true; >> for (unsigned i = 1, e = GEPI->getNumOperands(); i != e; ++i) >> if (!isa(GEPI->getOperand(i))) { >> AllConstant = false; >> break; >> } >> if (AllConstant) continue; > > The subscripts involved are not constant (they're based off the > induction variable, as you would expect in a loop), so that won't > work. Ok. I am actually more or less ok with the change. If this pessmize some code (which it probably) will, the fix is to teach some later passes to recover gracefully (easier said then done). Evan > > >>> Modified: >>> llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp >>> >>> Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp?rev=69631&r1=69630&r2=69631&view=diff >>> >>> = >>> = >>> = >>> = >>> = >>> = >>> = >>> = >>> = >>> = >>> ==================================================================== >>> --- llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp (original) >>> +++ llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp Mon Apr 20 >>> 17:19:33 2009 >>> @@ -89,6 +89,8 @@ >>> // Ignore instructions only used by the loop terminator. >>> } else if (isa(I)) { >>> // Ignore debug instructions >>> + } else if (isa(I) && I->hasOneUse()) { >>> + // Ignore GEP as they generally are subsumed into a load or >>> store. >>> } else if (isa(I)) { >>> // Estimate size overhead introduced by call instructions >>> which >>> // is higher than other instructions. Here 3 and 10 are magic >>> >>> >>> _______________________________________________ >>> llvm-commits mailing list >>> llvm-commits at cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From dpatel at apple.com Mon Apr 20 19:08:56 2009 From: dpatel at apple.com (Devang Patel) Date: Tue, 21 Apr 2009 00:08:56 -0000 Subject: [llvm-commits] [llvm] r69637 - /llvm/trunk/lib/CodeGen/AsmPrinter/DwarfWriter.cpp Message-ID: <200904210008.n3L08ucT020860@zion.cs.uiuc.edu> Author: dpatel Date: Mon Apr 20 19:08:56 2009 New Revision: 69637 URL: http://llvm.org/viewvc/llvm-project?rev=69637&view=rev Log: Fix Visual Studio 2008 build failure. Patch by Marius Wachtler Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfWriter.cpp Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfWriter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfWriter.cpp?rev=69637&r1=69636&r2=69637&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfWriter.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfWriter.cpp Mon Apr 20 19:08:56 2009 @@ -1164,9 +1164,9 @@ void AddVariable(DbgVariable *V) { Variables.push_back(V); } virtual bool isInlinedSubroutine() { return false; } - virtual unsigned getLine() { assert ( 0 && "Unexpected scope!"); } - virtual unsigned getColumn() { assert ( 0 && "Unexpected scope!"); } - virtual unsigned getFile() { assert ( 0 && "Unexpected scope!"); } + virtual unsigned getLine() { assert ( 0 && "Unexpected scope!"); return 0; } + virtual unsigned getColumn() { assert ( 0 && "Unexpected scope!"); return 0; } + virtual unsigned getFile() { assert ( 0 && "Unexpected scope!"); return 0; } }; From gohman at apple.com Mon Apr 20 19:47:47 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 21 Apr 2009 00:47:47 -0000 Subject: [llvm-commits] [llvm] r69640 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolution.h include/llvm/Analysis/ScalarEvolutionExpressions.h lib/Analysis/ScalarEvolution.cpp Message-ID: <200904210047.n3L0llc5021937@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 19:47:46 2009 New Revision: 69640 URL: http://llvm.org/viewvc/llvm-project?rev=69640&view=rev Log: Convert ScalarEvolution to use raw_ostream instead of OStream. Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h llvm/trunk/lib/Analysis/ScalarEvolution.cpp Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=69640&r1=69639&r2=69640&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Mon Apr 20 19:47:46 2009 @@ -93,7 +93,8 @@ /// print - Print out the internal representation of this scalar to the /// specified stream. This should really only be used for debugging /// purposes. - virtual void print(std::ostream &OS) const = 0; + virtual void print(raw_ostream &OS) const = 0; + void print(std::ostream &OS) const; void print(std::ostream *OS) const { if (OS) print(*OS); } /// dump - This method is used for debugging. @@ -101,6 +102,11 @@ void dump() const; }; + inline raw_ostream &operator<<(raw_ostream &OS, const SCEV &S) { + S.print(OS); + return OS; + } + inline std::ostream &operator<<(std::ostream &OS, const SCEV &S) { S.print(OS); return OS; @@ -118,8 +124,7 @@ virtual bool isLoopInvariant(const Loop *L) const; virtual const Type *getType() const; virtual bool hasComputableLoopEvolution(const Loop *L) const; - virtual void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + virtual void print(raw_ostream &OS) const; virtual SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, const SCEVHandle &Conc, @@ -331,6 +336,7 @@ virtual bool runOnFunction(Function &F); virtual void releaseMemory(); virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void print(raw_ostream &OS, const Module* = 0) const; virtual void print(std::ostream &OS, const Module* = 0) const; void print(std::ostream *OS, const Module* M = 0) const { if (OS) print(*OS, M); Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h?rev=69640&r1=69639&r2=69640&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h Mon Apr 20 19:47:46 2009 @@ -63,8 +63,7 @@ return true; } - virtual void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVConstant *S) { return true; } @@ -107,8 +106,7 @@ virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const; - virtual void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVTruncateExpr *S) { return true; } @@ -151,8 +149,7 @@ bool dominates(BasicBlock *BB, DominatorTree *DT) const; - virtual void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVZeroExtendExpr *S) { return true; } @@ -195,8 +192,7 @@ bool dominates(BasicBlock *BB, DominatorTree *DT) const; - virtual void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVSignExtendExpr *S) { return true; } @@ -266,8 +262,7 @@ virtual const char *getOperationStr() const = 0; virtual const Type *getType() const { return getOperand(0)->getType(); } - virtual void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVCommutativeExpr *S) { return true; } @@ -360,8 +355,7 @@ virtual const Type *getType() const; - void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVUDivExpr *S) { return true; } @@ -453,8 +447,7 @@ bool dominates(BasicBlock *BB, DominatorTree *DT) const; - virtual void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVAddRecExpr *S) { return true; } @@ -538,8 +531,7 @@ virtual const Type *getType() const; - virtual void print(std::ostream &OS) const; - void print(std::ostream *OS) const { if (OS) print(*OS); } + virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVUnknown *S) { return true; } Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69640&r1=69639&r2=69640&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Apr 20 19:47:46 2009 @@ -79,7 +79,7 @@ #include "llvm/Support/InstIterator.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/Streams.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include @@ -115,8 +115,13 @@ // SCEV::~SCEV() {} void SCEV::dump() const { - print(cerr); - cerr << '\n'; + print(errs()); + errs() << '\n'; +} + +void SCEV::print(std::ostream &o) const { + raw_os_ostream OS(o); + print(OS); } bool SCEV::isZero() const { @@ -150,7 +155,7 @@ return this; } -void SCEVCouldNotCompute::print(std::ostream &OS) const { +void SCEVCouldNotCompute::print(raw_ostream &OS) const { OS << "***COULDNOTCOMPUTE***"; } @@ -181,7 +186,7 @@ const Type *SCEVConstant::getType() const { return V->getType(); } -void SCEVConstant::print(std::ostream &OS) const { +void SCEVConstant::print(raw_ostream &OS) const { WriteAsOperand(OS, V, false); } @@ -210,7 +215,7 @@ return Op->dominates(BB, DT); } -void SCEVTruncateExpr::print(std::ostream &OS) const { +void SCEVTruncateExpr::print(raw_ostream &OS) const { OS << "(truncate " << *Op << " to " << *Ty << ")"; } @@ -235,7 +240,7 @@ return Op->dominates(BB, DT); } -void SCEVZeroExtendExpr::print(std::ostream &OS) const { +void SCEVZeroExtendExpr::print(raw_ostream &OS) const { OS << "(zeroextend " << *Op << " to " << *Ty << ")"; } @@ -262,7 +267,7 @@ return Op->dominates(BB, DT); } -void SCEVSignExtendExpr::print(std::ostream &OS) const { +void SCEVSignExtendExpr::print(raw_ostream &OS) const { OS << "(signextend " << *Op << " to " << *Ty << ")"; } @@ -278,7 +283,7 @@ Operands.end()))); } -void SCEVCommutativeExpr::print(std::ostream &OS) const { +void SCEVCommutativeExpr::print(raw_ostream &OS) const { assert(Operands.size() > 1 && "This plus expr shouldn't exist!"); const char *OpStr = getOperationStr(); OS << "(" << *Operands[0]; @@ -342,7 +347,7 @@ return LHS->dominates(BB, DT) && RHS->dominates(BB, DT); } -void SCEVUDivExpr::print(std::ostream &OS) const { +void SCEVUDivExpr::print(raw_ostream &OS) const { OS << "(" << *LHS << " /u " << *RHS << ")"; } @@ -403,7 +408,7 @@ } -void SCEVAddRecExpr::print(std::ostream &OS) const { +void SCEVAddRecExpr::print(raw_ostream &OS) const { OS << "{" << *Operands[0]; for (unsigned i = 1, e = Operands.size(); i != e; ++i) OS << ",+," << *Operands[i]; @@ -435,7 +440,7 @@ return V->getType(); } -void SCEVUnknown::print(std::ostream &OS) const { +void SCEVUnknown::print(raw_ostream &OS) const { if (isa(V->getType())) OS << "(ptrtoint " << *V->getType() << " "; WriteAsOperand(OS, V, false); @@ -2245,10 +2250,10 @@ } default: #if 0 - cerr << "ComputeBackedgeTakenCount "; + errs() << "ComputeBackedgeTakenCount "; if (ExitCond->getOperand(0)->getType()->isUnsigned()) - cerr << "[unsigned] "; - cerr << *LHS << " " + errs() << "[unsigned] "; + errs() << *LHS << " " << Instruction::getOpcodeName(Instruction::ICmp) << " " << *RHS << "\n"; #endif @@ -2369,9 +2374,9 @@ if (!isa(Result)) break; // Couldn't decide for sure if (cast(Result)->getValue().isMinValue()) { #if 0 - cerr << "\n***\n*** Computed loop count " << *ItCst - << "\n*** From global " << *GV << "*** BB: " << *L->getHeader() - << "***\n"; + errs() << "\n***\n*** Computed loop count " << *ItCst + << "\n*** From global " << *GV << "*** BB: " << *L->getHeader() + << "***\n"; #endif ++NumArrayLenItCounts; return SE.getConstant(ItCst); // Found terminating iteration! @@ -2873,8 +2878,8 @@ SCEVConstant *R2 = dyn_cast(Roots.second); if (R1) { #if 0 - cerr << "HFTZ: " << *V << " - sol#1: " << *R1 - << " sol#2: " << *R2 << "\n"; + errs() << "HFTZ: " << *V << " - sol#1: " << *R1 + << " sol#2: " << *R2 << "\n"; #endif // Pick the smallest positive root value. if (ConstantInt *CB = @@ -3326,7 +3331,7 @@ return ((ScalarEvolutionsImpl*)Impl)->deleteValueFromRecords(V); } -static void PrintLoopInfo(std::ostream &OS, const ScalarEvolution *SE, +static void PrintLoopInfo(raw_ostream &OS, const ScalarEvolution *SE, const Loop *L) { // Print all inner loops first for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) @@ -3348,7 +3353,7 @@ OS << "\n"; } -void ScalarEvolution::print(std::ostream &OS, const Module* ) const { +void ScalarEvolution::print(raw_ostream &OS, const Module* ) const { Function &F = ((ScalarEvolutionsImpl*)Impl)->F; LoopInfo &LI = ((ScalarEvolutionsImpl*)Impl)->LI; @@ -3379,3 +3384,8 @@ for (LoopInfo::iterator I = LI.begin(), E = LI.end(); I != E; ++I) PrintLoopInfo(OS, this, *I); } + +void ScalarEvolution::print(std::ostream &o, const Module *M) const { + raw_os_ostream OS(o); + print(OS, M); +} From gohman at apple.com Mon Apr 20 19:55:22 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 21 Apr 2009 00:55:22 -0000 Subject: [llvm-commits] [llvm] r69643 - /llvm/trunk/lib/Analysis/ScalarEvolution.cpp Message-ID: <200904210055.n3L0tNh9022199@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 19:55:22 2009 New Revision: 69643 URL: http://llvm.org/viewvc/llvm-project?rev=69643&view=rev Log: Move some assertion checks so they can do more complete checking. Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69643&r1=69642&r2=69643&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Apr 20 19:55:22 2009 @@ -201,10 +201,6 @@ assert((Op->getType()->isInteger() || isa(Op->getType())) && (Ty->isInteger() || isa(Ty)) && "Cannot truncate non-integer value!"); - assert((!Op->getType()->isInteger() || !Ty->isInteger() || - Op->getType()->getPrimitiveSizeInBits() > - Ty->getPrimitiveSizeInBits()) && - "This is not a truncating conversion!"); } SCEVTruncateExpr::~SCEVTruncateExpr() { @@ -255,8 +251,6 @@ assert((Op->getType()->isInteger() || isa(Op->getType())) && (Ty->isInteger() || isa(Ty)) && "Cannot sign extend non-integer value!"); - assert(Op->getType()->getPrimitiveSizeInBits() < Ty->getPrimitiveSizeInBits() - && "This is not an extending conversion!"); } SCEVSignExtendExpr::~SCEVSignExtendExpr() { @@ -654,6 +648,10 @@ //===----------------------------------------------------------------------===// SCEVHandle ScalarEvolution::getTruncateExpr(const SCEVHandle &Op, const Type *Ty) { + assert(getTargetData().getTypeSizeInBits(Op->getType()) > + getTargetData().getTypeSizeInBits(Ty) && + "This is not a truncating conversion!"); + if (SCEVConstant *SC = dyn_cast(Op)) return getUnknown( ConstantExpr::getTrunc(SC->getValue(), Ty)); @@ -702,6 +700,10 @@ } SCEVHandle ScalarEvolution::getSignExtendExpr(const SCEVHandle &Op, const Type *Ty) { + assert(getTargetData().getTypeSizeInBits(Op->getType()) < + getTargetData().getTypeSizeInBits(Ty) && + "This is not an extending conversion!"); + if (SCEVConstant *SC = dyn_cast(Op)) { const Type *IntTy = Ty; if (isa(IntTy)) IntTy = getTargetData().getIntPtrType(); From gohman at apple.com Mon Apr 20 20:07:12 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 21 Apr 2009 01:07:12 -0000 Subject: [llvm-commits] [llvm] r69644 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolution.h include/llvm/Analysis/ScalarEvolutionExpander.h lib/Analysis/ScalarEvolution.cpp lib/Analysis/ScalarEvolutionExpander.cpp lib/Transforms/Scalar/IndVarSimplify.cpp lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200904210107.n3L17Dxo022584@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 20:07:12 2009 New Revision: 69644 URL: http://llvm.org/viewvc/llvm-project?rev=69644&view=rev Log: Introduce encapsulation for ScalarEvolution's TargetData object, and refactor the code to minimize dependencies on TargetData. Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h llvm/trunk/lib/Analysis/ScalarEvolution.cpp llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=69644&r1=69643&r2=69644&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Mon Apr 20 20:07:12 2009 @@ -32,7 +32,6 @@ class Type; class SCEVHandle; class ScalarEvolution; - class TargetData; /// SCEV - This class represent an analyzed expression in the program. These /// are reference counted opaque objects that the client is not allowed to @@ -201,9 +200,21 @@ static char ID; // Pass identification, replacement for typeid ScalarEvolution() : FunctionPass(&ID), Impl(0) {} - // getTargetData - Return the TargetData object contained in this - // ScalarEvolution. - const TargetData &getTargetData() const; + /// isSCEVable - Test if values of the given type are analyzable within + /// the SCEV framework. This primarily includes integer types, and it + /// can optionally include pointer types if the ScalarEvolution class + /// has access to target-specific information. + bool isSCEVable(const Type *Ty) const; + + /// getTypeSizeInBits - Return the size in bits of the specified type, + /// for which isSCEVable must return true. + uint64_t getTypeSizeInBits(const Type *Ty) const; + + /// getEffectiveSCEVType - Return a type with the same bitwidth as + /// the given type and which represents how SCEV will treat the given + /// type, for which isSCEVable must return true. For pointer types, + /// this is the pointer-sized integer type. + const Type *getEffectiveSCEVType(const Type *Ty) const; /// getSCEV - Return a SCEV expression handle for the full generality of the /// specified expression. Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h?rev=69644&r1=69643&r2=69644&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h Mon Apr 20 20:07:12 2009 @@ -20,8 +20,6 @@ #include "llvm/Analysis/ScalarEvolutionExpressions.h" namespace llvm { - class TargetData; - /// SCEVExpander - This class uses information about analyze scalars to /// rewrite expressions in canonical form. /// @@ -31,7 +29,6 @@ struct SCEVExpander : public SCEVVisitor { ScalarEvolution &SE; LoopInfo &LI; - const TargetData &TD; std::map InsertedExpressions; std::set InsertedInstructions; @@ -39,8 +36,8 @@ friend struct SCEVVisitor; public: - SCEVExpander(ScalarEvolution &se, LoopInfo &li, const TargetData &td) - : SE(se), LI(li), TD(td) {} + SCEVExpander(ScalarEvolution &se, LoopInfo &li) + : SE(se), LI(li) {} LoopInfo &getLoopInfo() const { return LI; } @@ -85,6 +82,11 @@ /// we can to share the casts. Value *InsertCastOfTo(Instruction::CastOps opcode, Value *V, const Type *Ty); + + /// InsertNoopCastOfTo - Insert a cast of V to the specified type, + /// which must be possible with a noop cast. + Value *InsertNoopCastOfTo(Value *V, const Type *Ty); + /// InsertBinop - Insert the specified binary operator, doing a small amount /// of work to avoid inserting an obviously redundant operation. static Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69644&r1=69643&r2=69644&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Apr 20 20:07:12 2009 @@ -570,7 +570,7 @@ if (K > 1000) return SE.getCouldNotCompute(); - unsigned W = SE.getTargetData().getTypeSizeInBits(ResultTy); + unsigned W = SE.getTypeSizeInBits(ResultTy); // Calculate K! / 2^T and T; we divide out the factors of two before // multiplying for calculating K! / 2^T to avoid overflow. @@ -648,8 +648,7 @@ //===----------------------------------------------------------------------===// SCEVHandle ScalarEvolution::getTruncateExpr(const SCEVHandle &Op, const Type *Ty) { - assert(getTargetData().getTypeSizeInBits(Op->getType()) > - getTargetData().getTypeSizeInBits(Ty) && + assert(getTypeSizeInBits(Op->getType()) > getTypeSizeInBits(Ty) && "This is not a truncating conversion!"); if (SCEVConstant *SC = dyn_cast(Op)) @@ -677,13 +676,11 @@ SCEVHandle ScalarEvolution::getZeroExtendExpr(const SCEVHandle &Op, const Type *Ty) { - assert(getTargetData().getTypeSizeInBits(Op->getType()) < - getTargetData().getTypeSizeInBits(Ty) && + assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && "This is not an extending conversion!"); if (SCEVConstant *SC = dyn_cast(Op)) { - const Type *IntTy = Ty; - if (isa(IntTy)) IntTy = getTargetData().getIntPtrType(); + const Type *IntTy = getEffectiveSCEVType(Ty); Constant *C = ConstantExpr::getZExt(SC->getValue(), IntTy); if (IntTy != Ty) C = ConstantExpr::getIntToPtr(C, Ty); return getUnknown(C); @@ -700,13 +697,11 @@ } SCEVHandle ScalarEvolution::getSignExtendExpr(const SCEVHandle &Op, const Type *Ty) { - assert(getTargetData().getTypeSizeInBits(Op->getType()) < - getTargetData().getTypeSizeInBits(Ty) && + assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && "This is not an extending conversion!"); if (SCEVConstant *SC = dyn_cast(Op)) { - const Type *IntTy = Ty; - if (isa(IntTy)) IntTy = getTargetData().getIntPtrType(); + const Type *IntTy = getEffectiveSCEVType(Ty); Constant *C = ConstantExpr::getSExt(SC->getValue(), IntTy); if (IntTy != Ty) C = ConstantExpr::getIntToPtr(C, Ty); return getUnknown(C); @@ -1366,7 +1361,7 @@ /// TD - The target data information for the target we are targetting. /// - TargetData &TD; + TargetData *TD; /// UnknownValue - This SCEV is used to represent unknown trip counts and /// things. @@ -1389,9 +1384,25 @@ public: ScalarEvolutionsImpl(ScalarEvolution &se, Function &f, LoopInfo &li, - TargetData &td) + TargetData *td) : SE(se), F(f), LI(li), TD(td), UnknownValue(new SCEVCouldNotCompute()) {} + /// isSCEVable - Test if values of the given type are analyzable within + /// the SCEV framework. This primarily includes integer types, and it + /// can optionally include pointer types if the ScalarEvolution class + /// has access to target-specific information. + bool isSCEVable(const Type *Ty) const; + + /// getTypeSizeInBits - Return the size in bits of the specified type, + /// for which isSCEVable must return true. + uint64_t getTypeSizeInBits(const Type *Ty) const; + + /// getEffectiveSCEVType - Return a type with the same bitwidth as + /// the given type and which represents how SCEV will treat the given + /// type, for which isSCEVable must return true. For pointer types, + /// this is the pointer-sized integer type. + const Type *getEffectiveSCEVType(const Type *Ty) const; + SCEVHandle getCouldNotCompute(); /// getIntegerSCEV - Given an integer or FP type, create a constant for the @@ -1478,9 +1489,6 @@ /// that no dangling references are left around. void deleteValueFromRecords(Value *V); - /// getTargetData - Return the TargetData. - const TargetData &getTargetData() const; - private: /// createSCEV - We know that there is no SCEV for the specified value. /// Analyze the expression. @@ -1581,8 +1589,50 @@ } } -const TargetData &ScalarEvolutionsImpl::getTargetData() const { - return TD; +/// isSCEVable - Test if values of the given type are analyzable within +/// the SCEV framework. This primarily includes integer types, and it +/// can optionally include pointer types if the ScalarEvolution class +/// has access to target-specific information. +bool ScalarEvolutionsImpl::isSCEVable(const Type *Ty) const { + // Integers are always SCEVable. + if (Ty->isInteger()) + return true; + + // Pointers are SCEVable if TargetData information is available + // to provide pointer size information. + if (isa(Ty)) + return TD != NULL; + + // Otherwise it's not SCEVable. + return false; +} + +/// getTypeSizeInBits - Return the size in bits of the specified type, +/// for which isSCEVable must return true. +uint64_t ScalarEvolutionsImpl::getTypeSizeInBits(const Type *Ty) const { + assert(isSCEVable(Ty) && "Type is not SCEVable!"); + + // If we have a TargetData, use it! + if (TD) + return TD->getTypeSizeInBits(Ty); + + // Otherwise, we support only integer types. + assert(Ty->isInteger() && "isSCEVable permitted a non-SCEVable type!"); + return Ty->getPrimitiveSizeInBits(); +} + +/// getEffectiveSCEVType - Return a type with the same bitwidth as +/// the given type and which represents how SCEV will treat the given +/// type, for which isSCEVable must return true. For pointer types, +/// this is the pointer-sized integer type. +const Type *ScalarEvolutionsImpl::getEffectiveSCEVType(const Type *Ty) const { + assert(isSCEVable(Ty) && "Type is not SCEVable!"); + + if (Ty->isInteger()) + return Ty; + + assert(isa(Ty) && "Unexpected non-pointer non-integer type!"); + return TD->getIntPtrType(); } SCEVHandle ScalarEvolutionsImpl::getCouldNotCompute() { @@ -1592,7 +1642,7 @@ /// getSCEV - Return an existing SCEV if it exists, otherwise analyze the /// expression and create a new one. SCEVHandle ScalarEvolutionsImpl::getSCEV(Value *V) { - assert(V->getType() != Type::VoidTy && "Can't analyze void expressions!"); + assert(isSCEVable(V->getType()) && "Value is not SCEVable!"); std::map::iterator I = Scalars.find(V); if (I != Scalars.end()) return I->second; @@ -1604,8 +1654,7 @@ /// getIntegerSCEV - Given an integer or FP type, create a constant for the /// specified signed integer value and return a SCEV for the constant. SCEVHandle ScalarEvolutionsImpl::getIntegerSCEV(int Val, const Type *Ty) { - if (isa(Ty)) - Ty = TD.getIntPtrType(); + Ty = SE.getEffectiveSCEVType(Ty); Constant *C; if (Val == 0) C = Constant::getNullValue(Ty); @@ -1624,8 +1673,7 @@ return SE.getUnknown(ConstantExpr::getNeg(VC->getValue())); const Type *Ty = V->getType(); - if (isa(Ty)) - Ty = TD.getIntPtrType(); + Ty = SE.getEffectiveSCEVType(Ty); return SE.getMulExpr(V, SE.getConstant(ConstantInt::getAllOnesValue(Ty))); } @@ -1635,8 +1683,7 @@ return SE.getUnknown(ConstantExpr::getNot(VC->getValue())); const Type *Ty = V->getType(); - if (isa(Ty)) - Ty = TD.getIntPtrType(); + Ty = SE.getEffectiveSCEVType(Ty); SCEVHandle AllOnes = SE.getConstant(ConstantInt::getAllOnesValue(Ty)); return getMinusSCEV(AllOnes, V); } @@ -1656,12 +1703,12 @@ ScalarEvolutionsImpl::getTruncateOrZeroExtend(const SCEVHandle &V, const Type *Ty) { const Type *SrcTy = V->getType(); - assert((SrcTy->isInteger() || isa(SrcTy)) && - (Ty->isInteger() || isa(Ty)) && + assert((SrcTy->isInteger() || (TD && isa(SrcTy))) && + (Ty->isInteger() || (TD && isa(Ty))) && "Cannot truncate or zero extend with non-integer arguments!"); - if (TD.getTypeSizeInBits(SrcTy) == TD.getTypeSizeInBits(Ty)) + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) return V; // No conversion - if (TD.getTypeSizeInBits(SrcTy) > TD.getTypeSizeInBits(Ty)) + if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty)) return SE.getTruncateExpr(V, Ty); return SE.getZeroExtendExpr(V, Ty); } @@ -1673,12 +1720,12 @@ ScalarEvolutionsImpl::getTruncateOrSignExtend(const SCEVHandle &V, const Type *Ty) { const Type *SrcTy = V->getType(); - assert((SrcTy->isInteger() || isa(SrcTy)) && - (Ty->isInteger() || isa(Ty)) && + assert((SrcTy->isInteger() || (TD && isa(SrcTy))) && + (Ty->isInteger() || (TD && isa(Ty))) && "Cannot truncate or zero extend with non-integer arguments!"); - if (TD.getTypeSizeInBits(SrcTy) == TD.getTypeSizeInBits(Ty)) + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) return V; // No conversion - if (TD.getTypeSizeInBits(SrcTy) > TD.getTypeSizeInBits(Ty)) + if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty)) return SE.getTruncateExpr(V, Ty); return SE.getSignExtendExpr(V, Ty); } @@ -1806,66 +1853,66 @@ /// guaranteed to end in (at every loop iteration). It is, at the same time, /// the minimum number of times S is divisible by 2. For example, given {4,+,8} /// it returns 2. If S is guaranteed to be 0, it returns the bitwidth of S. -static uint32_t GetMinTrailingZeros(SCEVHandle S, const TargetData &TD) { +static uint32_t GetMinTrailingZeros(SCEVHandle S, const ScalarEvolution &SE) { if (SCEVConstant *C = dyn_cast(S)) return C->getValue()->getValue().countTrailingZeros(); if (SCEVTruncateExpr *T = dyn_cast(S)) - return std::min(GetMinTrailingZeros(T->getOperand(), TD), - (uint32_t)TD.getTypeSizeInBits(T->getType())); + return std::min(GetMinTrailingZeros(T->getOperand(), SE), + (uint32_t)SE.getTypeSizeInBits(T->getType())); if (SCEVZeroExtendExpr *E = dyn_cast(S)) { - uint32_t OpRes = GetMinTrailingZeros(E->getOperand(), TD); - return OpRes == TD.getTypeSizeInBits(E->getOperand()->getType()) ? - TD.getTypeSizeInBits(E->getOperand()->getType()) : OpRes; + uint32_t OpRes = GetMinTrailingZeros(E->getOperand(), SE); + return OpRes == SE.getTypeSizeInBits(E->getOperand()->getType()) ? + SE.getTypeSizeInBits(E->getOperand()->getType()) : OpRes; } if (SCEVSignExtendExpr *E = dyn_cast(S)) { - uint32_t OpRes = GetMinTrailingZeros(E->getOperand(), TD); - return OpRes == TD.getTypeSizeInBits(E->getOperand()->getType()) ? - TD.getTypeSizeInBits(E->getOperand()->getType()) : OpRes; + uint32_t OpRes = GetMinTrailingZeros(E->getOperand(), SE); + return OpRes == SE.getTypeSizeInBits(E->getOperand()->getType()) ? + SE.getTypeSizeInBits(E->getOperand()->getType()) : OpRes; } if (SCEVAddExpr *A = dyn_cast(S)) { // The result is the min of all operands results. - uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0), TD); + uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0), SE); for (unsigned i = 1, e = A->getNumOperands(); MinOpRes && i != e; ++i) - MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i), TD)); + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i), SE)); return MinOpRes; } if (SCEVMulExpr *M = dyn_cast(S)) { // The result is the sum of all operands results. - uint32_t SumOpRes = GetMinTrailingZeros(M->getOperand(0), TD); - uint32_t BitWidth = TD.getTypeSizeInBits(M->getType()); + uint32_t SumOpRes = GetMinTrailingZeros(M->getOperand(0), SE); + uint32_t BitWidth = SE.getTypeSizeInBits(M->getType()); for (unsigned i = 1, e = M->getNumOperands(); SumOpRes != BitWidth && i != e; ++i) - SumOpRes = std::min(SumOpRes + GetMinTrailingZeros(M->getOperand(i), TD), + SumOpRes = std::min(SumOpRes + GetMinTrailingZeros(M->getOperand(i), SE), BitWidth); return SumOpRes; } if (SCEVAddRecExpr *A = dyn_cast(S)) { // The result is the min of all operands results. - uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0), TD); + uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0), SE); for (unsigned i = 1, e = A->getNumOperands(); MinOpRes && i != e; ++i) - MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i), TD)); + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i), SE)); return MinOpRes; } if (SCEVSMaxExpr *M = dyn_cast(S)) { // The result is the min of all operands results. - uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0), TD); + uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0), SE); for (unsigned i = 1, e = M->getNumOperands(); MinOpRes && i != e; ++i) - MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i), TD)); + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i), SE)); return MinOpRes; } if (SCEVUMaxExpr *M = dyn_cast(S)) { // The result is the min of all operands results. - uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0), TD); + uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0), SE); for (unsigned i = 1, e = M->getNumOperands(); MinOpRes && i != e; ++i) - MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i), TD)); + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i), SE)); return MinOpRes; } @@ -1877,8 +1924,7 @@ /// Analyze the expression. /// SCEVHandle ScalarEvolutionsImpl::createSCEV(Value *V) { - if (!isa(V->getType()) && - !isa(V->getType())) + if (!isSCEVable(V->getType())) return SE.getUnknown(V); unsigned Opcode = Instruction::UserOp1; @@ -1913,7 +1959,7 @@ if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { SCEVHandle LHS = getSCEV(U->getOperand(0)); const APInt &CIVal = CI->getValue(); - if (GetMinTrailingZeros(LHS, TD) >= + if (GetMinTrailingZeros(LHS, SE) >= (CIVal.getBitWidth() - CIVal.countLeadingZeros())) return SE.getAddExpr(LHS, getSCEV(U->getOperand(1))); } @@ -1963,23 +2009,23 @@ case Instruction::BitCast: // BitCasts are no-op casts so we just eliminate the cast. - if ((U->getType()->isInteger() || - isa(U->getType())) && - (U->getOperand(0)->getType()->isInteger() || - isa(U->getOperand(0)->getType()))) + if (isSCEVable(U->getType()) && isSCEVable(U->getOperand(0)->getType())) return getSCEV(U->getOperand(0)); break; case Instruction::IntToPtr: + if (!TD) break; // Without TD we can't analyze pointers. return getTruncateOrZeroExtend(getSCEV(U->getOperand(0)), - TD.getIntPtrType()); + TD->getIntPtrType()); case Instruction::PtrToInt: + if (!TD) break; // Without TD we can't analyze pointers. return getTruncateOrZeroExtend(getSCEV(U->getOperand(0)), U->getType()); case Instruction::GetElementPtr: { - const Type *IntPtrTy = TD.getIntPtrType(); + if (!TD) break; // Without TD we can't analyze pointers. + const Type *IntPtrTy = TD->getIntPtrType(); Value *Base = U->getOperand(0); SCEVHandle TotalOffset = SE.getIntegerSCEV(0, IntPtrTy); gep_type_iterator GTI = gep_type_begin(U); @@ -1990,7 +2036,7 @@ // Compute the (potentially symbolic) offset in bytes for this index. if (const StructType *STy = dyn_cast(*GTI++)) { // For a struct, add the member offset. - const StructLayout &SL = *TD.getStructLayout(STy); + const StructLayout &SL = *TD->getStructLayout(STy); unsigned FieldNo = cast(Index)->getZExtValue(); uint64_t Offset = SL.getElementOffset(FieldNo); TotalOffset = SE.getAddExpr(TotalOffset, @@ -2004,7 +2050,7 @@ IntPtrTy); LocalOffset = SE.getMulExpr(LocalOffset, - SE.getIntegerSCEV(TD.getTypePaddedSize(*GTI), + SE.getIntegerSCEV(TD->getTypePaddedSize(*GTI), IntPtrTy)); TotalOffset = SE.getAddExpr(TotalOffset, LocalOffset); } @@ -3132,7 +3178,7 @@ // First check to see if the range contains zero. If not, the first // iteration exits. - unsigned BitWidth = SE.getTargetData().getTypeSizeInBits(getType()); + unsigned BitWidth = SE.getTypeSizeInBits(getType()); if (!Range.contains(APInt(BitWidth, 0))) return SE.getConstant(ConstantInt::get(getType(),0)); @@ -3226,7 +3272,7 @@ bool ScalarEvolution::runOnFunction(Function &F) { Impl = new ScalarEvolutionsImpl(*this, F, getAnalysis(), - getAnalysis()); + &getAnalysis()); return false; } @@ -3241,8 +3287,16 @@ AU.addRequiredTransitive(); } -const TargetData &ScalarEvolution::getTargetData() const { - return ((ScalarEvolutionsImpl*)Impl)->getTargetData(); +bool ScalarEvolution::isSCEVable(const Type *Ty) const { + return ((ScalarEvolutionsImpl*)Impl)->isSCEVable(Ty); +} + +uint64_t ScalarEvolution::getTypeSizeInBits(const Type *Ty) const { + return ((ScalarEvolutionsImpl*)Impl)->getTypeSizeInBits(Ty); +} + +const Type *ScalarEvolution::getEffectiveSCEVType(const Type *Ty) const { + return ((ScalarEvolutionsImpl*)Impl)->getEffectiveSCEVType(Ty); } SCEVHandle ScalarEvolution::getCouldNotCompute() { Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=69644&r1=69643&r2=69644&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Mon Apr 20 20:07:12 2009 @@ -15,7 +15,6 @@ #include "llvm/Analysis/ScalarEvolutionExpander.h" #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Target/TargetData.h" using namespace llvm; /// InsertCastOfTo - Insert a cast of V to the specified type, doing what @@ -27,12 +26,14 @@ return V; // Short-circuit unnecessary inttoptr<->ptrtoint casts. - if (opcode == Instruction::PtrToInt && Ty == TD.getIntPtrType()) - if (IntToPtrInst *ITP = dyn_cast(V)) - return ITP->getOperand(0); - if (opcode == Instruction::IntToPtr && V->getType() == TD.getIntPtrType()) - if (PtrToIntInst *PTI = dyn_cast(V)) - return PTI->getOperand(0); + if ((opcode == Instruction::PtrToInt || opcode == Instruction::IntToPtr) && + SE.getTypeSizeInBits(Ty) == SE.getTypeSizeInBits(V->getType())) + if (CastInst *CI = dyn_cast(V)) + if ((CI->getOpcode() == Instruction::PtrToInt || + CI->getOpcode() == Instruction::IntToPtr) && + SE.getTypeSizeInBits(CI->getType()) == + SE.getTypeSizeInBits(CI->getOperand(0)->getType())) + return CI->getOperand(0); // FIXME: keep track of the cast instruction. if (Constant *C = dyn_cast(V)) @@ -83,6 +84,19 @@ return CastInst::Create(opcode, V, Ty, V->getName(), IP); } +/// InsertNoopCastOfTo - Insert a cast of V to the specified type, +/// which must be possible with a noop cast. +Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) { + Instruction::CastOps Op = CastInst::getCastOpcode(V, false, Ty, false); + assert((Op == Instruction::BitCast || + Op == Instruction::Instruction::PtrToInt || + Op == Instruction::Instruction::IntToPtr) && + "InsertNoopCastOfTo cannot perform non-noop casts!"); + assert(SE.getTypeSizeInBits(V->getType()) == SE.getTypeSizeInBits(Ty) && + "InsertNoopCastOfTo cannot change sizes!"); + return InsertCastOfTo(Op, V, Ty); +} + /// InsertBinop - Insert the specified binary operator, doing a small amount /// of work to avoid inserting an obviously redundant operation. Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, @@ -113,23 +127,21 @@ } Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { - const Type *Ty = S->getType(); - if (isa(Ty)) Ty = TD.getIntPtrType(); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *V = expand(S->getOperand(S->getNumOperands()-1)); - V = InsertCastOfTo(CastInst::getCastOpcode(V, false, Ty, false), V, Ty); + V = InsertNoopCastOfTo(V, Ty); // Emit a bunch of add instructions for (int i = S->getNumOperands()-2; i >= 0; --i) { Value *W = expand(S->getOperand(i)); - W = InsertCastOfTo(CastInst::getCastOpcode(W, false, Ty, false), W, Ty); + W = InsertNoopCastOfTo(W, Ty); V = InsertBinop(Instruction::Add, V, W, InsertPt); } return V; } Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) { - const Type *Ty = S->getType(); - if (isa(Ty)) Ty = TD.getIntPtrType(); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); int FirstOp = 0; // Set if we should emit a subtract. if (const SCEVConstant *SC = dyn_cast(S->getOperand(0))) if (SC->getValue()->isAllOnesValue()) @@ -137,12 +149,12 @@ int i = S->getNumOperands()-2; Value *V = expand(S->getOperand(i+1)); - V = InsertCastOfTo(CastInst::getCastOpcode(V, false, Ty, false), V, Ty); + V = InsertNoopCastOfTo(V, Ty); // Emit a bunch of multiply instructions for (; i >= FirstOp; --i) { Value *W = expand(S->getOperand(i)); - W = InsertCastOfTo(CastInst::getCastOpcode(W, false, Ty, false), W, Ty); + W = InsertNoopCastOfTo(W, Ty); V = InsertBinop(Instruction::Mul, V, W, InsertPt); } @@ -153,11 +165,10 @@ } Value *SCEVExpander::visitUDivExpr(const SCEVUDivExpr *S) { - const Type *Ty = S->getType(); - if (isa(Ty)) Ty = TD.getIntPtrType(); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *LHS = expand(S->getLHS()); - LHS = InsertCastOfTo(CastInst::getCastOpcode(LHS, false, Ty, false), LHS, Ty); + LHS = InsertNoopCastOfTo(LHS, Ty); if (const SCEVConstant *SC = dyn_cast(S->getRHS())) { const APInt &RHS = SC->getValue()->getValue(); if (RHS.isPowerOf2()) @@ -167,27 +178,22 @@ } Value *RHS = expand(S->getRHS()); - RHS = InsertCastOfTo(CastInst::getCastOpcode(RHS, false, Ty, false), RHS, Ty); + RHS = InsertNoopCastOfTo(RHS, Ty); return InsertBinop(Instruction::UDiv, LHS, RHS, InsertPt); } Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { - const Type *Ty = S->getType(); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); const Loop *L = S->getLoop(); - // We cannot yet do fp recurrences, e.g. the xform of {X,+,F} --> X+{0,+,F} - assert((Ty->isInteger() || isa(Ty)) && - "Cannot expand fp recurrences yet!"); // {X,+,F} --> X + {0,+,F} if (!S->getStart()->isZero()) { Value *Start = expand(S->getStart()); - if (isa(Start->getType())) - Start = InsertCastOfTo(Instruction::PtrToInt, Start, TD.getIntPtrType()); + Start = InsertNoopCastOfTo(Start, Ty); std::vector NewOps(S->op_begin(), S->op_end()); NewOps[0] = SE.getIntegerSCEV(0, Ty); Value *Rest = expand(SE.getAddRecExpr(NewOps, L)); - if (isa(Rest->getType())) - Rest = InsertCastOfTo(Instruction::PtrToInt, Rest, TD.getIntPtrType()); + Rest = InsertNoopCastOfTo(Rest, Ty); // FIXME: look for an existing add to use. return InsertBinop(Instruction::Add, Rest, Start, InsertPt); @@ -227,8 +233,7 @@ // If this is a simple linear addrec, emit it now as a special case. if (S->isAffine()) { // {0,+,F} --> i*F Value *F = expand(S->getOperand(1)); - if (isa(F->getType())) - F = InsertCastOfTo(Instruction::PtrToInt, F, TD.getIntPtrType()); + F = InsertNoopCastOfTo(F, Ty); // IF the step is by one, just return the inserted IV. if (ConstantInt *CI = dyn_cast(F)) @@ -276,38 +281,33 @@ } Value *SCEVExpander::visitTruncateExpr(const SCEVTruncateExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *V = expand(S->getOperand()); - if (isa(V->getType())) - V = InsertCastOfTo(Instruction::PtrToInt, V, TD.getIntPtrType()); - return CastInst::CreateTruncOrBitCast(V, S->getType(), "tmp.", InsertPt); + V = InsertNoopCastOfTo(V, SE.getEffectiveSCEVType(V->getType())); + return CastInst::CreateTruncOrBitCast(V, Ty, "tmp.", InsertPt); } Value *SCEVExpander::visitZeroExtendExpr(const SCEVZeroExtendExpr *S) { - const Type *Ty = S->getType(); - if (isa(Ty)) Ty = TD.getIntPtrType(); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *V = expand(S->getOperand()); - if (isa(V->getType())) - V = InsertCastOfTo(Instruction::PtrToInt, V, TD.getIntPtrType()); + V = InsertNoopCastOfTo(V, SE.getEffectiveSCEVType(V->getType())); return CastInst::CreateZExtOrBitCast(V, Ty, "tmp.", InsertPt); } Value *SCEVExpander::visitSignExtendExpr(const SCEVSignExtendExpr *S) { - const Type *Ty = S->getType(); - if (isa(Ty)) Ty = TD.getIntPtrType(); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *V = expand(S->getOperand()); - if (isa(V->getType())) - V = InsertCastOfTo(Instruction::PtrToInt, V, TD.getIntPtrType()); + V = InsertNoopCastOfTo(V, SE.getEffectiveSCEVType(V->getType())); return CastInst::CreateSExtOrBitCast(V, Ty, "tmp.", InsertPt); } Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) { - const Type *Ty = S->getType(); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *LHS = expand(S->getOperand(0)); - LHS = InsertCastOfTo(CastInst::getCastOpcode(LHS, false, Ty, false), LHS, Ty); + LHS = InsertNoopCastOfTo(LHS, Ty); for (unsigned i = 1; i < S->getNumOperands(); ++i) { Value *RHS = expand(S->getOperand(i)); - RHS = InsertCastOfTo(CastInst::getCastOpcode(RHS, false, Ty, false), - RHS, Ty); + RHS = InsertNoopCastOfTo(RHS, Ty); Value *ICmp = new ICmpInst(ICmpInst::ICMP_SGT, LHS, RHS, "tmp", InsertPt); LHS = SelectInst::Create(ICmp, LHS, RHS, "smax", InsertPt); } @@ -315,13 +315,12 @@ } Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { - const Type *Ty = S->getType(); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *LHS = expand(S->getOperand(0)); - LHS = InsertCastOfTo(CastInst::getCastOpcode(LHS, false, Ty, false), LHS, Ty); + LHS = InsertNoopCastOfTo(LHS, Ty); for (unsigned i = 1; i < S->getNumOperands(); ++i) { Value *RHS = expand(S->getOperand(i)); - RHS = InsertCastOfTo(CastInst::getCastOpcode(RHS, false, Ty, false), - RHS, Ty); + RHS = InsertNoopCastOfTo(RHS, Ty); Value *ICmp = new ICmpInst(ICmpInst::ICMP_UGT, LHS, RHS, "tmp", InsertPt); LHS = SelectInst::Create(ICmp, LHS, RHS, "umax", InsertPt); } @@ -331,11 +330,11 @@ Value *SCEVExpander::expandCodeFor(SCEVHandle SH, const Type *Ty, Instruction *IP) { // Expand the code for this SCEV. - assert(TD.getTypeSizeInBits(Ty) == TD.getTypeSizeInBits(SH->getType()) && + assert(SE.getTypeSizeInBits(Ty) == SE.getTypeSizeInBits(SH->getType()) && "non-trivial casts should be done with the SCEVs directly!"); this->InsertPt = IP; Value *V = expand(SH); - return InsertCastOfTo(CastInst::getCastOpcode(V, false, Ty, false), V, Ty); + return InsertNoopCastOfTo(V, Ty); } Value *SCEVExpander::expand(const SCEV *S) { Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=69644&r1=69643&r2=69644&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Mon Apr 20 20:07:12 2009 @@ -50,7 +50,6 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/GetElementPtrTypeIterator.h" -#include "llvm/Target/TargetData.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Support/CommandLine.h" #include "llvm/ADT/SmallVector.h" @@ -67,7 +66,6 @@ namespace { class VISIBILITY_HIDDEN IndVarSimplify : public LoopPass { LoopInfo *LI; - TargetData *TD; ScalarEvolution *SE; bool Changed; public: @@ -82,7 +80,6 @@ AU.addRequiredID(LCSSAID); AU.addRequiredID(LoopSimplifyID); AU.addRequired(); - AU.addRequired(); AU.addPreserved(); AU.addPreservedID(LoopSimplifyID); AU.addPreservedID(LCSSAID); @@ -217,7 +214,7 @@ // Scan all of the instructions in the loop, looking at those that have // extra-loop users and which are recurrences. - SCEVExpander Rewriter(*SE, *LI, *TD); + SCEVExpander Rewriter(*SE, *LI); // We insert the code into the preheader of the loop if the loop contains // multiple exit blocks, or in the exit block if there is exactly one. @@ -350,7 +347,7 @@ /// induction-variable PHINode Phi is cast to. /// static const Type *getEffectiveIndvarType(const PHINode *Phi, - const TargetData *TD) { + const ScalarEvolution *SE) { const Type *Ty = Phi->getType(); for (Value::use_const_iterator UI = Phi->use_begin(), UE = Phi->use_end(); @@ -360,8 +357,13 @@ CandidateType = ZI->getDestTy(); else if (const SExtInst *SI = dyn_cast(UI)) CandidateType = SI->getDestTy(); + else if (const IntToPtrInst *IP = dyn_cast(UI)) + CandidateType = IP->getDestTy(); + else if (const PtrToIntInst *PI = dyn_cast(UI)) + CandidateType = PI->getDestTy(); if (CandidateType && - TD->getTypeSizeInBits(CandidateType) > TD->getTypeSizeInBits(Ty)) + SE->isSCEVable(CandidateType) && + SE->getTypeSizeInBits(CandidateType) > SE->getTypeSizeInBits(Ty)) Ty = CandidateType; } @@ -389,7 +391,7 @@ static const PHINode *TestOrigIVForWrap(const Loop *L, const BranchInst *BI, const Instruction *OrigCond, - const TargetData *TD, + const ScalarEvolution &SE, bool &NoSignedWrap, bool &NoUnsignedWrap, const ConstantInt* &InitialVal, @@ -462,7 +464,7 @@ if (const SExtInst *SI = dyn_cast(CmpLHS)) { if (!isa(CmpRHS) || !cast(CmpRHS)->getValue() - .isSignedIntN(TD->getTypeSizeInBits(IncrInst->getType()))) + .isSignedIntN(SE.getTypeSizeInBits(IncrInst->getType()))) return 0; IncrInst = SI->getOperand(0); } @@ -470,7 +472,7 @@ if (const ZExtInst *ZI = dyn_cast(CmpLHS)) { if (!isa(CmpRHS) || !cast(CmpRHS)->getValue() - .isIntN(TD->getTypeSizeInBits(IncrInst->getType()))) + .isIntN(SE.getTypeSizeInBits(IncrInst->getType()))) return 0; IncrInst = ZI->getOperand(0); } @@ -590,7 +592,6 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { LI = &getAnalysis(); - TD = &getAnalysis(); SE = &getAnalysis(); Changed = false; @@ -621,7 +622,7 @@ for (BasicBlock::iterator I = Header->begin(); isa(I); ++I) { PHINode *PN = cast(I); - if (PN->getType()->isInteger() || isa(PN->getType())) { + if (SE->isSCEVable(PN->getType())) { SCEVHandle SCEV = SE->getSCEV(PN); // FIXME: It is an extremely bad idea to indvar substitute anything more // complex than affine induction variables. Doing so will put expensive @@ -640,26 +641,25 @@ SmallSetVector SizesToInsert; if (!isa(BackedgeTakenCount)) { LargestType = BackedgeTakenCount->getType(); - if (isa(LargestType)) - LargestType = TD->getIntPtrType(); + LargestType = SE->getEffectiveSCEVType(LargestType); SizesToInsert.insert(LargestType); } for (unsigned i = 0, e = IndVars.size(); i != e; ++i) { const PHINode *PN = IndVars[i].first; const Type *PNTy = PN->getType(); - if (isa(PNTy)) PNTy = TD->getIntPtrType(); + PNTy = SE->getEffectiveSCEVType(PNTy); SizesToInsert.insert(PNTy); - const Type *EffTy = getEffectiveIndvarType(PN, TD); - if (isa(EffTy)) EffTy = TD->getIntPtrType(); + const Type *EffTy = getEffectiveIndvarType(PN, SE); + EffTy = SE->getEffectiveSCEVType(EffTy); SizesToInsert.insert(EffTy); if (!LargestType || - TD->getTypeSizeInBits(EffTy) > - TD->getTypeSizeInBits(LargestType)) + SE->getTypeSizeInBits(EffTy) > + SE->getTypeSizeInBits(LargestType)) LargestType = EffTy; } // Create a rewriter object which we'll use to transform the code with. - SCEVExpander Rewriter(*SE, *LI, *TD); + SCEVExpander Rewriter(*SE, *LI); // Now that we know the largest of of the induction variables in this loop, // insert a canonical induction variable of the largest size. @@ -683,7 +683,7 @@ if (Instruction *OrigCond = dyn_cast(BI->getCondition())) { // Determine if the OrigIV will ever undergo overflow. OrigControllingPHI = - TestOrigIVForWrap(L, BI, OrigCond, TD, + TestOrigIVForWrap(L, BI, OrigCond, *SE, NoSignedWrap, NoUnsignedWrap, InitialVal, IncrVal, LimitVal); Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=69644&r1=69643&r2=69644&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Apr 20 20:07:12 2009 @@ -26,7 +26,6 @@ #include "llvm/Transforms/Utils/AddrModeMatcher.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" -#include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/CFG.h" @@ -112,8 +111,6 @@ LoopInfo *LI; DominatorTree *DT; ScalarEvolution *SE; - const TargetData *TD; - const Type *UIntPtrTy; bool Changed; /// IVUsesByStride - Keep track of all uses of induction variables that we @@ -156,7 +153,6 @@ AU.addRequiredID(LoopSimplifyID); AU.addRequired(); AU.addRequired(); - AU.addRequired(); AU.addRequired(); AU.addPreserved(); } @@ -485,11 +481,11 @@ /// return true. Otherwise, return false. bool LoopStrengthReduce::AddUsersIfInteresting(Instruction *I, Loop *L, SmallPtrSet &Processed) { - if (!I->getType()->isInteger() && !isa(I->getType())) + if (!SE->isSCEVable(I->getType())) return false; // Void and FP expressions cannot be reduced. // LSR is not APInt clean, do not touch integers bigger than 64-bits. - if (TD->getTypeSizeInBits(I->getType()) > 64) + if (SE->getTypeSizeInBits(I->getType()) > 64) return false; if (!Processed.insert(I)) @@ -1174,14 +1170,12 @@ const Type *Ty2) { if (Ty1 == Ty2) return false; + if (SE->getEffectiveSCEVType(Ty1) == SE->getEffectiveSCEVType(Ty2)) + return false; if (Ty1->canLosslesslyBitCastTo(Ty2)) return false; if (TLI && TLI->isTruncateFree(Ty1, Ty2)) return false; - if (isa(Ty2) && Ty1->canLosslesslyBitCastTo(UIntPtrTy)) - return false; - if (isa(Ty1) && Ty2->canLosslesslyBitCastTo(UIntPtrTy)) - return false; return true; } @@ -1468,7 +1462,6 @@ /// static PHINode *InsertAffinePhi(SCEVHandle Start, SCEVHandle Step, const Loop *L, - const TargetData *TD, SCEVExpander &Rewriter) { assert(Start->isLoopInvariant(L) && "New PHI start is not loop invariant!"); assert(Step->isLoopInvariant(L) && "New PHI stride is not loop invariant!"); @@ -1477,7 +1470,7 @@ BasicBlock *Preheader = L->getLoopPreheader(); BasicBlock *LatchBlock = L->getLoopLatch(); const Type *Ty = Start->getType(); - if (isa(Ty)) Ty = TD->getIntPtrType(); + Ty = Rewriter.SE.getEffectiveSCEVType(Ty); PHINode *PN = PHINode::Create(Ty, "lsr.iv", Header->begin()); PN->addIncoming(Rewriter.expandCodeFor(Start, Ty, Preheader->getTerminator()), @@ -1564,7 +1557,7 @@ SCEVHandle Imm = UsersToProcess[i].Imm; SCEVHandle Base = UsersToProcess[i].Base; SCEVHandle Start = SE->getAddExpr(CommonExprs, Base, Imm); - PHINode *Phi = InsertAffinePhi(Start, Stride, L, TD, + PHINode *Phi = InsertAffinePhi(Start, Stride, L, PreheaderRewriter); // Loop over all the users with the same base. do { @@ -1591,7 +1584,7 @@ DOUT << " Inserting new PHI:\n"; PHINode *Phi = InsertAffinePhi(SE->getUnknown(CommonBaseV), - Stride, L, TD, + Stride, L, PreheaderRewriter); // Remember this in case a later stride is multiple of this. @@ -1695,9 +1688,7 @@ // a register operand, which potentially restricts what stride values are // valid. bool HaveCommonExprs = !CommonExprs->isZero(); - const Type *ReplacedTy = CommonExprs->getType(); - if (isa(ReplacedTy)) ReplacedTy = TD->getIntPtrType(); // If all uses are addresses, consider sinking the immediate part of the // common expression back into uses if they can fit in the immediate fields. @@ -1739,14 +1730,14 @@ << *Stride << ":\n" << " Common base: " << *CommonExprs << "\n"; - SCEVExpander Rewriter(*SE, *LI, *TD); - SCEVExpander PreheaderRewriter(*SE, *LI, *TD); + SCEVExpander Rewriter(*SE, *LI); + SCEVExpander PreheaderRewriter(*SE, *LI); BasicBlock *Preheader = L->getLoopPreheader(); Instruction *PreInsertPt = Preheader->getTerminator(); BasicBlock *LatchBlock = L->getLoopLatch(); - Value *CommonBaseV = ConstantInt::get(ReplacedTy, 0); + Value *CommonBaseV = Constant::getNullValue(ReplacedTy); SCEVHandle RewriteFactor = SE->getIntegerSCEV(0, ReplacedTy); IVExpr ReuseIV(SE->getIntegerSCEV(0, Type::Int32Ty), @@ -1837,10 +1828,10 @@ SCEVHandle RewriteExpr = SE->getUnknown(RewriteOp); - if (TD->getTypeSizeInBits(RewriteOp->getType()) != - TD->getTypeSizeInBits(ReplacedTy)) { - assert(TD->getTypeSizeInBits(RewriteOp->getType()) > - TD->getTypeSizeInBits(ReplacedTy) && + if (SE->getTypeSizeInBits(RewriteOp->getType()) != + SE->getTypeSizeInBits(ReplacedTy)) { + assert(SE->getTypeSizeInBits(RewriteOp->getType()) > + SE->getTypeSizeInBits(ReplacedTy) && "Unexpected widening cast!"); RewriteExpr = SE->getTruncateExpr(RewriteExpr, ReplacedTy); } @@ -1868,13 +1859,13 @@ // it here. if (!ReuseIV.Base->isZero()) { SCEVHandle typedBase = ReuseIV.Base; - if (TD->getTypeSizeInBits(RewriteExpr->getType()) != - TD->getTypeSizeInBits(ReuseIV.Base->getType())) { + if (SE->getTypeSizeInBits(RewriteExpr->getType()) != + SE->getTypeSizeInBits(ReuseIV.Base->getType())) { // It's possible the original IV is a larger type than the new IV, // in which case we have to truncate the Base. We checked in // RequiresTypeConversion that this is valid. - assert(TD->getTypeSizeInBits(RewriteExpr->getType()) < - TD->getTypeSizeInBits(ReuseIV.Base->getType()) && + assert(SE->getTypeSizeInBits(RewriteExpr->getType()) < + SE->getTypeSizeInBits(ReuseIV.Base->getType()) && "Unexpected lengthening conversion!"); typedBase = SE->getTruncateExpr(ReuseIV.Base, RewriteExpr->getType()); @@ -1959,8 +1950,8 @@ // e.g. // 4, -1, X, 1, 2 ==> 1, -1, 2, 4, X struct StrideCompare { - const TargetData *TD; - explicit StrideCompare(const TargetData *td) : TD(td) {} + const ScalarEvolution *SE; + explicit StrideCompare(const ScalarEvolution *se) : SE(se) {} bool operator()(const SCEVHandle &LHS, const SCEVHandle &RHS) { const SCEVConstant *LHSC = dyn_cast(LHS); @@ -1980,8 +1971,8 @@ // If it's the same value but different type, sort by bit width so // that we emit larger induction variables before smaller // ones, letting the smaller be re-written in terms of larger ones. - return TD->getTypeSizeInBits(RHS->getType()) < - TD->getTypeSizeInBits(LHS->getType()); + return SE->getTypeSizeInBits(RHS->getType()) < + SE->getTypeSizeInBits(LHS->getType()); } return LHSC && !RHSC; } @@ -2014,17 +2005,17 @@ ICmpInst::Predicate Predicate = Cond->getPredicate(); int64_t CmpSSInt = SC->getValue()->getSExtValue(); - unsigned BitWidth = TD->getTypeSizeInBits((*CondStride)->getType()); + unsigned BitWidth = SE->getTypeSizeInBits((*CondStride)->getType()); uint64_t SignBit = 1ULL << (BitWidth-1); const Type *CmpTy = Cond->getOperand(0)->getType(); const Type *NewCmpTy = NULL; - unsigned TyBits = TD->getTypeSizeInBits(CmpTy); + unsigned TyBits = SE->getTypeSizeInBits(CmpTy); unsigned NewTyBits = 0; SCEVHandle *NewStride = NULL; Value *NewCmpLHS = NULL; Value *NewCmpRHS = NULL; int64_t Scale = 1; - SCEVHandle NewOffset = SE->getIntegerSCEV(0, UIntPtrTy); + SCEVHandle NewOffset = SE->getIntegerSCEV(0, CmpTy); if (ConstantInt *C = dyn_cast(Cond->getOperand(1))) { int64_t CmpVal = C->getValue().getSExtValue(); @@ -2070,7 +2061,8 @@ continue; NewCmpTy = NewCmpLHS->getType(); - NewTyBits = TD->getTypeSizeInBits(NewCmpTy); + NewTyBits = SE->getTypeSizeInBits(NewCmpTy); + const Type *NewCmpIntTy = IntegerType::get(NewTyBits); if (RequiresTypeConversion(NewCmpTy, CmpTy)) { // Check if it is possible to rewrite it using // an iv / stride of a smaller integer type. @@ -2111,13 +2103,13 @@ if (!isa(NewCmpTy)) NewCmpRHS = ConstantInt::get(NewCmpTy, NewCmpVal); else { - ConstantInt *CI = ConstantInt::get(UIntPtrTy, NewCmpVal); + ConstantInt *CI = ConstantInt::get(NewCmpIntTy, NewCmpVal); NewCmpRHS = ConstantExpr::getIntToPtr(CI, NewCmpTy); } NewOffset = TyBits == NewTyBits ? SE->getMulExpr(CondUse->Offset, SE->getConstant(ConstantInt::get(CmpTy, Scale))) - : SE->getConstant(ConstantInt::get(IntegerType::get(NewTyBits), + : SE->getConstant(ConstantInt::get(NewCmpIntTy, cast(CondUse->Offset)->getValue()->getSExtValue()*Scale)); break; } @@ -2335,7 +2327,7 @@ const Type *SrcTy = PH->getType(); int Mantissa = DestTy->getFPMantissaWidth(); if (Mantissa == -1) continue; - if ((int)TD->getTypeSizeInBits(SrcTy) > Mantissa) + if ((int)SE->getTypeSizeInBits(SrcTy) > Mantissa) continue; unsigned Entry, Latch; @@ -2462,8 +2454,6 @@ LI = &getAnalysis(); DT = &getAnalysis(); SE = &getAnalysis(); - TD = &getAnalysis(); - UIntPtrTy = TD->getIntPtrType(); Changed = false; // Find all uses of induction variables in this loop, and categorize @@ -2481,7 +2471,7 @@ #endif // Sort the StrideOrder so we process larger strides first. - std::stable_sort(StrideOrder.begin(), StrideOrder.end(), StrideCompare(TD)); + std::stable_sort(StrideOrder.begin(), StrideOrder.end(), StrideCompare(SE)); // Optimize induction variables. Some indvar uses can be transformed to use // strides that will be needed for other purposes. A common example of this From gohman at apple.com Mon Apr 20 20:11:19 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 21 Apr 2009 01:11:19 -0000 Subject: [llvm-commits] [llvm] r69645 - /llvm/trunk/lib/Analysis/ScalarEvolution.cpp Message-ID: <200904210111.n3L1BJGG022711@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 20:11:19 2009 New Revision: 69645 URL: http://llvm.org/viewvc/llvm-project?rev=69645&view=rev Log: Usage getAnalysisToUpdate for TargetData, per PR760. Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69645&r1=69644&r2=69645&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Apr 20 20:11:19 2009 @@ -3272,7 +3272,7 @@ bool ScalarEvolution::runOnFunction(Function &F) { Impl = new ScalarEvolutionsImpl(*this, F, getAnalysis(), - &getAnalysis()); + getAnalysisIfAvailable()); return false; } @@ -3284,7 +3284,6 @@ void ScalarEvolution::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequiredTransitive(); - AU.addRequiredTransitive(); } bool ScalarEvolution::isSCEVable(const Type *Ty) const { From gohman at apple.com Mon Apr 20 20:25:57 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 21 Apr 2009 01:25:57 -0000 Subject: [llvm-commits] [llvm] r69649 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolutionExpressions.h lib/Analysis/ScalarEvolution.cpp lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200904210125.n3L1PvMx023188@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 20:25:57 2009 New Revision: 69649 URL: http://llvm.org/viewvc/llvm-project?rev=69649&view=rev Log: Factor out a common base class from SCEVTruncateExpr, SCEVZeroExtendExpr, and SCEVSignExtendExpr. Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h llvm/trunk/lib/Analysis/ScalarEvolution.cpp llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h?rev=69649&r1=69648&r2=69649&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h Mon Apr 20 20:25:57 2009 @@ -73,16 +73,16 @@ }; //===--------------------------------------------------------------------===// - /// SCEVTruncateExpr - This class represents a truncation of an integer value - /// to a smaller integer value. + /// SCEVCastExpr - This is the base class for unary cast operator classes. /// - class SCEVTruncateExpr : public SCEV { - friend class ScalarEvolution; - + class SCEVCastExpr : public SCEV { + protected: SCEVHandle Op; const Type *Ty; - SCEVTruncateExpr(const SCEVHandle &op, const Type *ty); - virtual ~SCEVTruncateExpr(); + + SCEVCastExpr(unsigned SCEVTy, const SCEVHandle &op, const Type *ty); + virtual ~SCEVCastExpr(); + public: const SCEVHandle &getOperand() const { return Op; } virtual const Type *getType() const { return Ty; } @@ -95,6 +95,28 @@ return Op->hasComputableLoopEvolution(L); } + virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVCastExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scTruncate || + S->getSCEVType() == scZeroExtend || + S->getSCEVType() == scSignExtend; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVTruncateExpr - This class represents a truncation of an integer value + /// to a smaller integer value. + /// + class SCEVTruncateExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVTruncateExpr(const SCEVHandle &op, const Type *ty); + virtual ~SCEVTruncateExpr(); + + public: SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, const SCEVHandle &Conc, ScalarEvolution &SE) const { @@ -104,8 +126,6 @@ return SE.getTruncateExpr(H, Ty); } - virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const; - virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -119,25 +139,13 @@ /// SCEVZeroExtendExpr - This class represents a zero extension of a small /// integer value to a larger integer value. /// - class SCEVZeroExtendExpr : public SCEV { + class SCEVZeroExtendExpr : public SCEVCastExpr { friend class ScalarEvolution; - SCEVHandle Op; - const Type *Ty; SCEVZeroExtendExpr(const SCEVHandle &op, const Type *ty); virtual ~SCEVZeroExtendExpr(); - public: - const SCEVHandle &getOperand() const { return Op; } - virtual const Type *getType() const { return Ty; } - - virtual bool isLoopInvariant(const Loop *L) const { - return Op->isLoopInvariant(L); - } - - virtual bool hasComputableLoopEvolution(const Loop *L) const { - return Op->hasComputableLoopEvolution(L); - } + public: SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, const SCEVHandle &Conc, ScalarEvolution &SE) const { @@ -147,8 +155,6 @@ return SE.getZeroExtendExpr(H, Ty); } - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -162,25 +168,13 @@ /// SCEVSignExtendExpr - This class represents a sign extension of a small /// integer value to a larger integer value. /// - class SCEVSignExtendExpr : public SCEV { + class SCEVSignExtendExpr : public SCEVCastExpr { friend class ScalarEvolution; - SCEVHandle Op; - const Type *Ty; SCEVSignExtendExpr(const SCEVHandle &op, const Type *ty); virtual ~SCEVSignExtendExpr(); - public: - const SCEVHandle &getOperand() const { return Op; } - virtual const Type *getType() const { return Ty; } - - virtual bool isLoopInvariant(const Loop *L) const { - return Op->isLoopInvariant(L); - } - - virtual bool hasComputableLoopEvolution(const Loop *L) const { - return Op->hasComputableLoopEvolution(L); - } + public: SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, const SCEVHandle &Conc, ScalarEvolution &SE) const { @@ -190,8 +184,6 @@ return SE.getSignExtendExpr(H, Ty); } - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - virtual void print(raw_ostream &OS) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -207,8 +199,6 @@ /// operators. /// class SCEVCommutativeExpr : public SCEV { - friend class ScalarEvolution; - std::vector Operands; protected: Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69649&r1=69648&r2=69649&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Apr 20 20:25:57 2009 @@ -190,6 +190,16 @@ WriteAsOperand(OS, V, false); } +SCEVCastExpr::SCEVCastExpr(unsigned SCEVTy, + const SCEVHandle &op, const Type *ty) + : SCEV(SCEVTy), Op(op), Ty(ty) {} + +SCEVCastExpr::~SCEVCastExpr() {} + +bool SCEVCastExpr::dominates(BasicBlock *BB, DominatorTree *DT) const { + return Op->dominates(BB, DT); +} + // SCEVTruncates - Only allow the creation of one SCEVTruncateExpr for any // particular input. Don't use a SCEVHandle here, or else the object will // never be deleted! @@ -197,7 +207,7 @@ SCEVTruncateExpr*> > SCEVTruncates; SCEVTruncateExpr::SCEVTruncateExpr(const SCEVHandle &op, const Type *ty) - : SCEV(scTruncate), Op(op), Ty(ty) { + : SCEVCastExpr(scTruncate, op, ty) { assert((Op->getType()->isInteger() || isa(Op->getType())) && (Ty->isInteger() || isa(Ty)) && "Cannot truncate non-integer value!"); @@ -207,10 +217,6 @@ SCEVTruncates->erase(std::make_pair(Op, Ty)); } -bool SCEVTruncateExpr::dominates(BasicBlock *BB, DominatorTree *DT) const { - return Op->dominates(BB, DT); -} - void SCEVTruncateExpr::print(raw_ostream &OS) const { OS << "(truncate " << *Op << " to " << *Ty << ")"; } @@ -222,7 +228,7 @@ SCEVZeroExtendExpr*> > SCEVZeroExtends; SCEVZeroExtendExpr::SCEVZeroExtendExpr(const SCEVHandle &op, const Type *ty) - : SCEV(scZeroExtend), Op(op), Ty(ty) { + : SCEVCastExpr(scZeroExtend, op, ty) { assert((Op->getType()->isInteger() || isa(Op->getType())) && (Ty->isInteger() || isa(Ty)) && "Cannot zero extend non-integer value!"); @@ -232,10 +238,6 @@ SCEVZeroExtends->erase(std::make_pair(Op, Ty)); } -bool SCEVZeroExtendExpr::dominates(BasicBlock *BB, DominatorTree *DT) const { - return Op->dominates(BB, DT); -} - void SCEVZeroExtendExpr::print(raw_ostream &OS) const { OS << "(zeroextend " << *Op << " to " << *Ty << ")"; } @@ -247,7 +249,7 @@ SCEVSignExtendExpr*> > SCEVSignExtends; SCEVSignExtendExpr::SCEVSignExtendExpr(const SCEVHandle &op, const Type *ty) - : SCEV(scSignExtend), Op(op), Ty(ty) { + : SCEVCastExpr(scSignExtend, op, ty) { assert((Op->getType()->isInteger() || isa(Op->getType())) && (Ty->isInteger() || isa(Ty)) && "Cannot sign extend non-integer value!"); @@ -257,10 +259,6 @@ SCEVSignExtends->erase(std::make_pair(Op, Ty)); } -bool SCEVSignExtendExpr::dominates(BasicBlock *BB, DominatorTree *DT) const { - return Op->dominates(BB, DT); -} - void SCEVSignExtendExpr::print(raw_ostream &OS) const { OS << "(signextend " << *Op << " to " << *Ty << ")"; } Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=69649&r1=69648&r2=69649&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Apr 20 20:25:57 2009 @@ -300,12 +300,8 @@ return containsAddRecFromDifferentLoop(DE->getLHS(), L) || containsAddRecFromDifferentLoop(DE->getRHS(), L); #endif - if (const SCEVTruncateExpr *TE = dyn_cast(S)) - return containsAddRecFromDifferentLoop(TE->getOperand(), L); - if (const SCEVZeroExtendExpr *ZE = dyn_cast(S)) - return containsAddRecFromDifferentLoop(ZE->getOperand(), L); - if (const SCEVSignExtendExpr *SE = dyn_cast(S)) - return containsAddRecFromDifferentLoop(SE->getOperand(), L); + if (const SCEVCastExpr *CE = dyn_cast(S)) + return containsAddRecFromDifferentLoop(CE->getOperand(), L); return false; } From gohman at apple.com Mon Apr 20 20:41:18 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 21 Apr 2009 01:41:18 -0000 Subject: [llvm-commits] [llvm] r69651 - /llvm/trunk/lib/Analysis/ScalarEvolution.cpp Message-ID: <200904210141.n3L1fIou023665@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 20:41:18 2009 New Revision: 69651 URL: http://llvm.org/viewvc/llvm-project?rev=69651&view=rev Log: This FIXME is fixed, now that SCEV understands pointers. Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69651&r1=69650&r2=69651&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Apr 20 20:41:18 2009 @@ -2234,9 +2234,6 @@ Cond = ICmpInst::getSwappedPredicate(Cond); } - // FIXME: think about handling pointer comparisons! i.e.: - // while (P != P+100) ++P; - // If we have a comparison of a chrec against a constant, try to use value // ranges to answer this query. if (SCEVConstant *RHSC = dyn_cast(RHS)) From sanjiv.gupta at microchip.com Mon Apr 20 21:09:14 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Tue, 21 Apr 2009 07:39:14 +0530 Subject: [llvm-commits] [llvm] r69605 - in /llvm/trunk: lib/Target/PIC16/PIC16AsmPrinter.cpp lib/Target/PIC16/PIC16AsmPrinter.h tools/Makefile In-Reply-To: References: <200904201659.n3KGxjGa006363@zion.cs.uiuc.edu> Message-ID: <49ED2ACA.7070602@microchip.com> Anton Korobeynikov wrote: > Hello, Sanjiv > > >> ============================================================================== >> --- llvm/trunk/tools/Makefile (original) >> +++ llvm/trunk/tools/Makefile Mon Apr 20 11:59:35 2009 >> @@ -20,7 +20,7 @@ >> llc llvm-ranlib llvm-ar llvm-nm \ >> llvm-ld llvm-prof llvm-link \ >> lli gccas gccld llvm-extract llvm-db \ >> - bugpoint llvm-bcanalyzer llvm-stub llvmc >> + bugpoint llvm-bcanalyzer llvm-stub llvmc clang >> > Did you really want to commit this hunk? > > No, It got in accidentally. From gohman at apple.com Mon Apr 20 21:26:00 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 21 Apr 2009 02:26:00 -0000 Subject: [llvm-commits] [llvm] r69655 - /llvm/trunk/lib/Analysis/ScalarEvolution.cpp Message-ID: <200904210226.n3L2Q0js024894@zion.cs.uiuc.edu> Author: djg Date: Mon Apr 20 21:26:00 2009 New Revision: 69655 URL: http://llvm.org/viewvc/llvm-project?rev=69655&view=rev Log: Teach ScalarEvolution how to recognize zext-inreg and sext-inreg, as they appear in LLVM IR. This isn't particularly interesting on its own; this is just setting up some infrastructure. Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69655&r1=69654&r2=69655&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Apr 20 21:26:00 2009 @@ -1947,6 +1947,19 @@ case Instruction::Sub: return SE.getMinusSCEV(getSCEV(U->getOperand(0)), getSCEV(U->getOperand(1))); + case Instruction::And: + // For an expression like x&255 that merely masks off the high bits, + // use zext(trunc(x)) as the SCEV expression. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + const APInt &A = CI->getValue(); + unsigned Ones = A.countTrailingOnes(); + if (APIntOps::isMask(Ones, A)) + return + SE.getZeroExtendExpr(SE.getTruncateExpr(getSCEV(U->getOperand(0)), + IntegerType::get(Ones)), + U->getType()); + } + break; case Instruction::Or: // If the RHS of the Or is a constant, we may have something like: // X*4+1 which got turned into X*4|1. Handle this as an Add so loop @@ -1996,6 +2009,20 @@ } break; + case Instruction::AShr: + // For a two-shift sext-inreg, use sext(trunc(x)) as the SCEV expression. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) + if (Instruction *L = dyn_cast(U->getOperand(0))) + if (L->getOpcode() == Instruction::Shl && + L->getOperand(1) == U->getOperand(1)) { + uint64_t Amt = CI->getZExtValue(); + return + SE.getSignExtendExpr(SE.getTruncateExpr(getSCEV(L->getOperand(0)), + IntegerType::get(Amt)), + U->getType()); + } + break; + case Instruction::Trunc: return SE.getTruncateExpr(getSCEV(U->getOperand(0)), U->getType()); From clattner at apple.com Mon Apr 20 23:00:00 2009 From: clattner at apple.com (Chris Lattner) Date: Mon, 20 Apr 2009 21:00:00 -0700 Subject: [llvm-commits] [llvm] r69631 - /llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp In-Reply-To: References: <200904202219.n3KMJYsf017409@zion.cs.uiuc.edu> Message-ID: <616D42B0-A799-4387-856F-989988D3F5F5@apple.com> On Apr 20, 2009, at 3:32 PM, Evan Cheng wrote: >> Well... That's not entirely true. Each GEP can also become a several >> instructions. Is there a test case to demonstrate the merit of this >> change? >> > > How about changing it to what InlineCost.cpp does? Better yet, change both to use if GEP->hasAllConstantIndices() :) -Chris From baldrick at free.fr Tue Apr 21 00:32:29 2009 From: baldrick at free.fr (Duncan Sands) Date: Tue, 21 Apr 2009 07:32:29 +0200 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <49EC40C4.1020301@microchip.com> References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> <200904200933.39786.baldrick@free.fr> <49EC40C4.1020301@microchip.com> Message-ID: <200904210732.32368.baldrick@free.fr> Hi Sanjiv, > >> Before trying to introduce/eliminate cast/ext/trunc to make indices type as > >> pointer type, make sure that the pointer size is a valid sequential index type. I think a better approach would be to add a "get preferred type for GEP indices" method to TargetData. This would return getIntPtrType on most targets, and i16 on PIC16. Then change this transform to use the type given by that method rather than getIntPtrType. Ciao, Duncan. > >> > > > > what's this about? Got a testcase? > > > > Ciao, > > > > Duncan. > > > > > Hi Duncan, > > Here it is > http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-April/021785.html > > - Sanjiv > >> Modified: > >> llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > >> > >> Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69574&r1=69573&r2=69574&view=diff > >> > >> ============================================================================== > >> --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) > >> +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Apr 20 01:05:54 2009 > >> @@ -10695,7 +10695,12 @@ > >> gep_type_iterator GTI = gep_type_begin(GEP); > >> for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); > >> i != e; ++i, ++GTI) { > >> - if (isa(*GTI)) { > >> + // Before trying to eliminate/introduce cast/ext/trunc to make > >> + // indices as pointer types, make sure that the pointer size > >> + // makes a valid sequential index. > >> + const SequentialType *ST = dyn_cast(*GTI); > >> + Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); > >> + if (ST && ST->indexValid(PtrTypeVal)) { > >> if (CastInst *CI = dyn_cast(*i)) { > >> if (CI->getOpcode() == Instruction::ZExt || > >> CI->getOpcode() == Instruction::SExt) { > >> > >> > >> _______________________________________________ > >> llvm-commits mailing list > >> llvm-commits at cs.uiuc.edu > >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > >> > >> > > > > > > From sanjiv.gupta at microchip.com Tue Apr 21 00:54:52 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Tue, 21 Apr 2009 05:54:52 -0000 Subject: [llvm-commits] [llvm] r69665 - in /llvm/trunk/lib/Target/PIC16: PIC16ISelLowering.cpp PIC16ISelLowering.h Message-ID: <200904210554.n3L5sqJB031241@zion.cs.uiuc.edu> Author: sgupta Date: Tue Apr 21 00:54:51 2009 New Revision: 69665 URL: http://llvm.org/viewvc/llvm-project?rev=69665&view=rev Log: Handle direct aggregate type arguments. Modified: llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h Modified: llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp?rev=69665&r1=69664&r2=69665&view=diff ============================================================================== --- llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp Tue Apr 21 00:54:51 2009 @@ -527,9 +527,6 @@ MachineFrameInfo *MFI = MF.getFrameInfo(); const std::string Name = Func->getName(); - char *tmpName = new char [strlen(Name.c_str()) + 8]; - sprintf(tmpName, "%s.frame", Name.c_str()); - ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); FrameIndexSDNode *FR = dyn_cast(Op); // FrameIndices are not stack offsets. But they represent the request @@ -538,9 +535,19 @@ // with, we need to traverse all the FrameIndices available earlier in // the list and add their requested size. unsigned FIndex = FR->getIndex(); - Offset = 0; - for (unsigned i=0; igetObjectSize(i); + char *tmpName = new char [strlen(Name.c_str()) + 8]; + if (FIndex < ReservedFrameCount) { + sprintf(tmpName, "%s.frame", Name.c_str()); + ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); + Offset = 0; + for (unsigned i=0; igetObjectSize(i); + } + } else { + // FrameIndex has been made for some temporary storage + sprintf(tmpName, "%s.tmp", Name.c_str()); + ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); + Offset = GetTmpOffsetForFI(FIndex, MFI->getObjectSize(FIndex)); } return; @@ -891,12 +898,7 @@ for (unsigned i = 0, ArgOffset = RetVals; i < NumOps; i++) { // Get the arguments Arg = TheCall->getArg(i); - // If argument is FrameIndex then map it with temporary - if (Arg.getOpcode() == PIC16ISD::Lo || Arg.getOpcode() == PIC16ISD::Hi) { - if (Arg.getOperand(0).getOpcode() == ISD::TargetFrameIndex) { - Arg = LegalizeFrameArgument(Arg, dl, DAG); - } - } + Ops.clear(); Ops.push_back(Chain); Ops.push_back(Arg); @@ -915,36 +917,6 @@ } SDValue PIC16TargetLowering:: -LegalizeFrameArgument(SDValue Arg, DebugLoc dl, SelectionDAG &DAG) { - MachineFunction &MF = DAG.getMachineFunction(); - const Function *Func = MF.getFunction(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - const std::string Name = Func->getName(); - - // Caller creates the stack storage to pass the aggregate type - // as argument. So it should be relative to tmp variable. - SDValue FI = Arg.getOperand(0); - char *tmpName = new char [strlen(Name.c_str()) + 8]; - sprintf(tmpName, "%s.tmp", Name.c_str()); - SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); - FrameIndexSDNode *FR = dyn_cast(FI); - - unsigned FIndex = FR->getIndex(); - // Reserve space in tmp variable for the aggregate type - int FrameOffset = GetTmpOffsetForFI(FIndex, MFI->getObjectSize(FIndex)); - - if (Arg.getOpcode() == PIC16ISD::Lo) { - // Lo part of frame index - SDValue FrameConst = DAG.getConstant(FrameOffset, MVT::i8); - return DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, ES, FrameConst); - } else { - // Hi part of frame index - SDValue FrameConst = DAG.getConstant(FrameOffset + 1, MVT::i8); - return DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, ES, FrameConst); - } -} - -SDValue PIC16TargetLowering:: LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue ArgLabel, SDValue InFlag, SelectionDAG &DAG) { CallSDNode *TheCall = dyn_cast(Op); @@ -975,12 +947,6 @@ for (unsigned i=ArgCount, Offset = 0; igetArg(i); - // If argument is FrameIndex then map it with temporary - if (Arg.getOpcode() == PIC16ISD::Lo || Arg.getOpcode() == PIC16ISD::Hi) { - if (Arg.getOperand(0).getOpcode() == ISD::TargetFrameIndex) { - Arg = LegalizeFrameArgument(Arg, dl, DAG); - } - } StoreOffset = (Offset + AddressOffset); // Store the argument on frame @@ -1455,6 +1421,17 @@ return DAG.getNode(Op.getOpcode(), dl, Tys, NewVal, Op.getOperand(1)); } +void PIC16TargetLowering::InitReservedFrameCount(const Function *F) { + unsigned NumArgs = F->arg_size(); + + bool isVoidFunc = (F->getReturnType()->getTypeID() == Type::VoidTyID); + + if (isVoidFunc) + ReservedFrameCount = NumArgs; + else + ReservedFrameCount = NumArgs + 1; +} + // LowerFORMAL_ARGUMENTS - Argument values are loaded from the // .args + offset. All arguments are already broken to leaglized // types, so the offset just runs from 0 to NumArgVals - 1. @@ -1467,13 +1444,16 @@ SDValue Chain = Op.getOperand(0); // Formal arguments' chain - // Reset the map of FI and TmpOffset - ResetTmpOffsetMap(); // Get the callee's name to create the .args label to pass args. MachineFunction &MF = DAG.getMachineFunction(); const Function *F = MF.getFunction(); std::string FuncName = F->getName(); + // Reset the map of FI and TmpOffset + ResetTmpOffsetMap(); + // Initialize the ReserveFrameCount + InitReservedFrameCount(F); + // Create the .args external symbol. char *tmpName = new char [strlen(FuncName.c_str()) + 6]; sprintf(tmpName, "%s.args", FuncName.c_str()); Modified: llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h?rev=69665&r1=69664&r2=69665&view=diff ============================================================================== --- llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h (original) +++ llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h Tue Apr 21 00:54:51 2009 @@ -139,6 +139,7 @@ // new offset and returns. unsigned GetTmpOffsetForFI(unsigned FI, unsigned slot_size); void ResetTmpOffsetMap() { FiTmpOffsetMap.clear(); SetTmpSize(0); } + void InitReservedFrameCount(const Function *F); // Return the size of Tmp variable unsigned GetTmpSize() { return TmpSize; } @@ -168,7 +169,6 @@ void LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, SDValue &ES, int &Offset); - SDValue LegalizeFrameArgument(SDValue Arg, DebugLoc dl, SelectionDAG &DAG); // CALL node should have all legal operands only. Legalize all non-legal // operands of CALL node and then return the new call will all operands @@ -216,6 +216,11 @@ // This maps maintain zero based indexes for these FIs. std::map FiTmpOffsetMap; unsigned TmpSize; + + // These are the frames for return value and argument passing + // These FrameIndices will be expanded to foo.frame external symbol + // and all others will be expanded to foo.tmp external symbol. + unsigned ReservedFrameCount; }; } // namespace llvm From sanjiv.gupta at microchip.com Tue Apr 21 01:48:26 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Tue, 21 Apr 2009 12:18:26 +0530 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <200904210732.32368.baldrick@free.fr> References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> <200904200933.39786.baldrick@free.fr> <49EC40C4.1020301@microchip.com> <200904210732.32368.baldrick@free.fr> Message-ID: <49ED6C3A.8070909@microchip.com> Duncan Sands wrote: > Hi Sanjiv, > > >>>> Before trying to introduce/eliminate cast/ext/trunc to make indices type as >>>> pointer type, make sure that the pointer size is a valid sequential index type. >>>> > > I think a better approach would be to add a "get preferred type for GEP indices" > method to TargetData. This would return getIntPtrType on most targets, and i16 > on PIC16. Then change this transform to use the type given by that method rather > than getIntPtrType. > I think you meant i32 on PIC16, because i16 indices are still not allowed to GEP. > Ciao, > > Duncan. > > >>>> >>>> >>> what's this about? Got a testcase? >>> >>> Ciao, >>> >>> Duncan. >>> >>> >>> >> Hi Duncan, >> >> Here it is >> http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-April/021785.html >> >> - Sanjiv >> >>>> Modified: >>>> llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >>>> >>>> Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69574&r1=69573&r2=69574&view=diff >>>> >>>> ============================================================================== >>>> --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) >>>> +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Apr 20 01:05:54 2009 >>>> @@ -10695,7 +10695,12 @@ >>>> gep_type_iterator GTI = gep_type_begin(GEP); >>>> for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); >>>> i != e; ++i, ++GTI) { >>>> - if (isa(*GTI)) { >>>> + // Before trying to eliminate/introduce cast/ext/trunc to make >>>> + // indices as pointer types, make sure that the pointer size >>>> + // makes a valid sequential index. >>>> + const SequentialType *ST = dyn_cast(*GTI); >>>> + Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); >>>> + if (ST && ST->indexValid(PtrTypeVal)) { >>>> if (CastInst *CI = dyn_cast(*i)) { >>>> if (CI->getOpcode() == Instruction::ZExt || >>>> CI->getOpcode() == Instruction::SExt) { >>>> >>>> >>>> _______________________________________________ >>>> llvm-commits mailing list >>>> llvm-commits at cs.uiuc.edu >>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >>>> >>>> >>>> >>> >>> >> > > From baldrick at free.fr Tue Apr 21 02:52:18 2009 From: baldrick at free.fr (Duncan Sands) Date: Tue, 21 Apr 2009 09:52:18 +0200 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <49ED6C3A.8070909@microchip.com> References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> <200904210732.32368.baldrick@free.fr> <49ED6C3A.8070909@microchip.com> Message-ID: <200904210952.19433.baldrick@free.fr> Hi Sanjiv, > >>>> Before trying to introduce/eliminate cast/ext/trunc to make indices type as > >>>> pointer type, make sure that the pointer size is a valid sequential index type. > >>>> > > > > I think a better approach would be to add a "get preferred type for GEP indices" > > method to TargetData. This would return getIntPtrType on most targets, and i16 > > on PIC16. Then change this transform to use the type given by that method rather > > than getIntPtrType. > > > I think you meant i32 on PIC16, because i16 indices are still not > allowed to GEP. sure, if that's what PIC16 wants. Anyway, the point is to decouple the GEP index type from pointer types in a clean way, by introducing new abstractions. Ciao, Duncan. From rafael.espindola at gmail.com Tue Apr 21 03:22:11 2009 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Tue, 21 Apr 2009 08:22:11 -0000 Subject: [llvm-commits] [llvm] r69672 - in /llvm/trunk/lib/Target/X86: X86Instr64bit.td X86InstrInfo.td Message-ID: <200904210822.n3L8MC4C008483@zion.cs.uiuc.edu> Author: rafael Date: Tue Apr 21 03:22:09 2009 New Revision: 69672 URL: http://llvm.org/viewvc/llvm-project?rev=69672&view=rev Log: TLS_addr64 and TLS_addr32 define RDI and EAX. They don't use them. This fixes PR4002. Modified: llvm/trunk/lib/Target/X86/X86Instr64bit.td llvm/trunk/lib/Target/X86/X86InstrInfo.td Modified: llvm/trunk/lib/Target/X86/X86Instr64bit.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Instr64bit.td?rev=69672&r1=69671&r2=69672&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Tue Apr 21 03:22:09 2009 @@ -1303,7 +1303,7 @@ // Thread Local Storage Instructions //===----------------------------------------------------------------------===// -let hasSideEffects = 1, Uses = [RDI] in +let hasSideEffects = 1, Defs = [RDI] in def TLS_addr64 : I<0, Pseudo, (outs), (ins i64imm:$sym), ".byte\t0x66; leaq\t${sym:mem}(%rip), %rdi; .word\t0x6666; rex64", [(X86tlsaddr tglobaltlsaddr:$sym)]>, Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=69672&r1=69671&r2=69672&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Tue Apr 21 03:22:09 2009 @@ -2977,7 +2977,7 @@ // Thread Local Storage Instructions // -let hasSideEffects = 1, Uses = [EAX, EBX] in +let hasSideEffects = 1, Uses = [EBX], Defs = [EAX] in def TLS_addr32 : I<0, Pseudo, (outs), (ins i32imm:$sym), "leal\t${sym:mem}(,%ebx,1), %eax", [(X86tlsaddr tglobaltlsaddr:$sym)]>, From baldrick at free.fr Tue Apr 21 04:44:47 2009 From: baldrick at free.fr (Duncan Sands) Date: Tue, 21 Apr 2009 09:44:47 -0000 Subject: [llvm-commits] [llvm] r69673 - /llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Message-ID: <200904210944.n3L9imRa012047@zion.cs.uiuc.edu> Author: baldrick Date: Tue Apr 21 04:44:39 2009 New Revision: 69673 URL: http://llvm.org/viewvc/llvm-project?rev=69673&view=rev Log: Get rid of what looks like a copy-and-pasted typo. Spotted by gcc-4.5. Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=69673&r1=69672&r2=69673&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Apr 21 04:44:39 2009 @@ -9075,7 +9075,7 @@ } if (DestReg) { Res.first = DestReg; - Res.second = Res.second = X86::GR8RegisterClass; + Res.second = X86::GR8RegisterClass; } } else if (VT == MVT::i32) { unsigned DestReg = 0; @@ -9092,7 +9092,7 @@ } if (DestReg) { Res.first = DestReg; - Res.second = Res.second = X86::GR32RegisterClass; + Res.second = X86::GR32RegisterClass; } } else if (VT == MVT::i64) { unsigned DestReg = 0; @@ -9109,7 +9109,7 @@ } if (DestReg) { Res.first = DestReg; - Res.second = Res.second = X86::GR64RegisterClass; + Res.second = X86::GR64RegisterClass; } } } else if (Res.second == X86::FR32RegisterClass || From asl at math.spbu.ru Tue Apr 21 11:04:14 2009 From: asl at math.spbu.ru (Anton Korobeynikov) Date: Tue, 21 Apr 2009 16:04:14 -0000 Subject: [llvm-commits] [llvm] r69677 - /llvm/trunk/utils/GenLibDeps.pl Message-ID: <200904211604.n3LG4FOg025566@zion.cs.uiuc.edu> Author: asl Date: Tue Apr 21 11:04:14 2009 New Revision: 69677 URL: http://llvm.org/viewvc/llvm-project?rev=69677&view=rev Log: 'The "or die" is intended to catch the case where nm returned a non-zero exit status, so nm will already have printed some error messages.' Patch by Jay Foad! Modified: llvm/trunk/utils/GenLibDeps.pl Modified: llvm/trunk/utils/GenLibDeps.pl URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/GenLibDeps.pl?rev=69677&r1=69676&r2=69677&view=diff ============================================================================== --- llvm/trunk/utils/GenLibDeps.pl (original) +++ llvm/trunk/utils/GenLibDeps.pl Tue Apr 21 11:04:14 2009 @@ -66,7 +66,7 @@ # this strips both LF and CRLF. $libdefs{$_} = $lib; } - close DEFS; + close DEFS or die "nm failed"; } # Gather definitions from the object files. @@ -79,7 +79,7 @@ # this strips both LF and CRLF. $objdefs{$_} = $obj; } - close DEFS; + close DEFS or die "nm failed"; } # Generate one entry in the
list. This generates the
and
elements @@ -113,7 +113,7 @@ } } } - close UNDEFS; + close UNDEFS or die "nm failed"; unless(keys %DepLibs) { # above failed open UNDEFS, "$nmPath -g -u $Directory/$lib |"; @@ -138,6 +138,7 @@ } } } + close UNDEFS or die "nm failed"; } for my $key (sort keys %DepLibs) { From asl at math.spbu.ru Tue Apr 21 11:04:41 2009 From: asl at math.spbu.ru (Anton Korobeynikov) Date: Tue, 21 Apr 2009 16:04:41 -0000 Subject: [llvm-commits] [llvm] r69678 - /llvm/trunk/lib/System/Win32/DynamicLibrary.inc Message-ID: <200904211604.n3LG4fL9025602@zion.cs.uiuc.edu> Author: asl Date: Tue Apr 21 11:04:41 2009 New Revision: 69678 URL: http://llvm.org/viewvc/llvm-project?rev=69678&view=rev Log: Drop obsolete reference to __eprintf. Patch by Jay Foad! Modified: llvm/trunk/lib/System/Win32/DynamicLibrary.inc Modified: llvm/trunk/lib/System/Win32/DynamicLibrary.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Win32/DynamicLibrary.inc?rev=69678&r1=69677&r2=69678&view=diff ============================================================================== --- llvm/trunk/lib/System/Win32/DynamicLibrary.inc (original) +++ llvm/trunk/lib/System/Win32/DynamicLibrary.inc Tue Apr 21 11:04:41 2009 @@ -138,7 +138,6 @@ EXPLICIT_SYMBOL_DEF(__ashrdi3); EXPLICIT_SYMBOL_DEF(__cmpdi2); EXPLICIT_SYMBOL_DEF(__divdi3); - EXPLICIT_SYMBOL_DEF(__eprintf); EXPLICIT_SYMBOL_DEF(__fixdfdi); EXPLICIT_SYMBOL_DEF(__fixsfdi); EXPLICIT_SYMBOL_DEF(__fixunsdfdi); @@ -176,7 +175,6 @@ EXPLICIT_SYMBOL(__ashrdi3); EXPLICIT_SYMBOL(__cmpdi2); EXPLICIT_SYMBOL(__divdi3); - EXPLICIT_SYMBOL(__eprintf); EXPLICIT_SYMBOL(__fixdfdi); EXPLICIT_SYMBOL(__fixsfdi); EXPLICIT_SYMBOL(__fixunsdfdi); From asl at math.spbu.ru Tue Apr 21 11:04:56 2009 From: asl at math.spbu.ru (Anton Korobeynikov) Date: Tue, 21 Apr 2009 16:04:56 -0000 Subject: [llvm-commits] [llvm] r69679 - /llvm/trunk/lib/System/Win32/Signals.inc Message-ID: <200904211604.n3LG4uRm025629@zion.cs.uiuc.edu> Author: asl Date: Tue Apr 21 11:04:56 2009 New Revision: 69679 URL: http://llvm.org/viewvc/llvm-project?rev=69679&view=rev Log: Silence warnings. Patch by Jay Foad! Modified: llvm/trunk/lib/System/Win32/Signals.inc Modified: llvm/trunk/lib/System/Win32/Signals.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Win32/Signals.inc?rev=69679&r1=69678&r2=69679&view=diff ============================================================================== --- llvm/trunk/lib/System/Win32/Signals.inc (original) +++ llvm/trunk/lib/System/Win32/Signals.inc Tue Apr 21 11:04:56 2009 @@ -188,10 +188,10 @@ // Print the PC in hexadecimal. DWORD PC = StackFrame.AddrPC.Offset; - fprintf(stderr, "%08X", PC); + fprintf(stderr, "%08lX", PC); // Print the parameters. Assume there are four. - fprintf(stderr, " (0x%08X 0x%08X 0x%08X 0x%08X)", StackFrame.Params[0], + fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2], StackFrame.Params[3]); // Verify the PC belongs to a module in this process. @@ -215,7 +215,7 @@ buffer[511] = 0; if (dwDisp > 0) - fprintf(stderr, ", %s()+%04d bytes(s)", symbol->Name, dwDisp); + fprintf(stderr, ", %s()+%04lu bytes(s)", symbol->Name, dwDisp); else fprintf(stderr, ", %s", symbol->Name); @@ -224,9 +224,9 @@ memset(&line, 0, sizeof(line)); line.SizeOfStruct = sizeof(line); if (SymGetLineFromAddr(hProcess, PC, &dwDisp, &line)) { - fprintf(stderr, ", %s, line %d", line.FileName, line.LineNumber); + fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber); if (dwDisp > 0) - fprintf(stderr, "+%04d byte(s)", dwDisp); + fprintf(stderr, "+%04lu byte(s)", dwDisp); } fputc('\n', stderr); From dalej at apple.com Tue Apr 21 11:37:42 2009 From: dalej at apple.com (Dale Johannesen) Date: Tue, 21 Apr 2009 09:37:42 -0700 Subject: [llvm-commits] [llvm] r69631 - /llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp In-Reply-To: <616D42B0-A799-4387-856F-989988D3F5F5@apple.com> References: <200904202219.n3KMJYsf017409@zion.cs.uiuc.edu> <616D42B0-A799-4387-856F-989988D3F5F5@apple.com> Message-ID: <6BD261F7-27A4-4EE8-B88B-B9D061A57092@apple.com> On Apr 20, 2009, at 9:00 PMPDT, Chris Lattner wrote: > On Apr 20, 2009, at 3:32 PM, Evan Cheng wrote: >>> Well... That's not entirely true. Each GEP can also become a several >>> instructions. Is there a test case to demonstrate the merit of this >>> change? >>> >> >> How about changing it to what InlineCost.cpp does? > > Better yet, change both to use if GEP->hasAllConstantIndices() :) I explained why that won't work. What we actually need to do is figure out which GEP's are going to become instructions and which aren't, which is of course target-dependent. I'm hoping to avoid that:) From sabre at nondot.org Tue Apr 21 11:52:14 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 21 Apr 2009 16:52:14 -0000 Subject: [llvm-commits] [llvm] r69680 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/2009-04-21-ZeroLengthMemSet.ll Message-ID: <200904211652.n3LGqE9E027940@zion.cs.uiuc.edu> Author: lattner Date: Tue Apr 21 11:52:12 2009 New Revision: 69680 URL: http://llvm.org/viewvc/llvm-project?rev=69680&view=rev Log: fix a crash on a pointless but valid zero-length memset, rdar://6808691 Added: llvm/trunk/test/Transforms/ScalarRepl/2009-04-21-ZeroLengthMemSet.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=69680&r1=69679&r2=69680&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Tue Apr 21 11:52:12 2009 @@ -1431,20 +1431,22 @@ if (MemSetInst *MSI = dyn_cast(User)) { assert(MSI->getRawDest() == Ptr && "Consistency error!"); unsigned NumBytes = cast(MSI->getLength())->getZExtValue(); - unsigned Val = cast(MSI->getValue())->getZExtValue(); - - // Compute the value replicated the right number of times. - APInt APVal(NumBytes*8, Val); + if (NumBytes != 0) { + unsigned Val = cast(MSI->getValue())->getZExtValue(); + + // Compute the value replicated the right number of times. + APInt APVal(NumBytes*8, Val); - // Splat the value if non-zero. - if (Val) - for (unsigned i = 1; i != NumBytes; ++i) - APVal |= APVal << 8; - - Value *Old = Builder.CreateLoad(NewAI, (NewAI->getName()+".in").c_str()); - Value *New = ConvertScalar_InsertValue(ConstantInt::get(APVal), Old, - Offset, Builder); - Builder.CreateStore(New, NewAI); + // Splat the value if non-zero. + if (Val) + for (unsigned i = 1; i != NumBytes; ++i) + APVal |= APVal << 8; + + Value *Old = Builder.CreateLoad(NewAI, (NewAI->getName()+".in").c_str()); + Value *New = ConvertScalar_InsertValue(ConstantInt::get(APVal), Old, + Offset, Builder); + Builder.CreateStore(New, NewAI); + } MSI->eraseFromParent(); continue; } Added: llvm/trunk/test/Transforms/ScalarRepl/2009-04-21-ZeroLengthMemSet.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2009-04-21-ZeroLengthMemSet.ll?rev=69680&view=auto ============================================================================== --- llvm/trunk/test/Transforms/ScalarRepl/2009-04-21-ZeroLengthMemSet.ll (added) +++ llvm/trunk/test/Transforms/ScalarRepl/2009-04-21-ZeroLengthMemSet.ll Tue Apr 21 11:52:12 2009 @@ -0,0 +1,16 @@ +; RUN: llvm-as < %s | opt -scalarrepl | llvm-dis +; rdar://6808691 +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "x86_64-apple-darwin9.0" + type <{ i32, i16, i8, i8, i64, i64, i16, [0 x i16] }> + +define i32 @foo() { +entry: + %.compoundliteral = alloca %0 + %tmp228 = getelementptr %0* %.compoundliteral, i32 0, i32 7 + %tmp229 = bitcast [0 x i16]* %tmp228 to i8* + call void @llvm.memset.i64(i8* %tmp229, i8 0, i64 0, i32 2) + unreachable +} + +declare void @llvm.memset.i64(i8* nocapture, i8, i64, i32) nounwind From dpatel at apple.com Tue Apr 21 12:20:37 2009 From: dpatel at apple.com (Devang Patel) Date: Tue, 21 Apr 2009 17:20:37 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r69683 - /llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Message-ID: <200904211720.n3LHKbUD028994@zion.cs.uiuc.edu> Author: dpatel Date: Tue Apr 21 12:20:37 2009 New Revision: 69683 URL: http://llvm.org/viewvc/llvm-project?rev=69683&view=rev Log: If llvm value is set then use value name as linkage name while emitting debug info. 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=69683&r1=69682&r2=69683&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Tue Apr 21 12:20:37 2009 @@ -182,6 +182,12 @@ static const char *getLinkageName(tree Node) { + // Use llvm value name as linkage name if it is available. + if (DECL_LLVM_SET_P(Node)) { + Value *V = DECL_LLVM(Node); + return V->getNameStart(); + } + tree decl_name = DECL_NAME(Node); if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL) { if (TREE_PUBLIC(Node) && From dpatel at apple.com Tue Apr 21 12:21:01 2009 From: dpatel at apple.com (Devang Patel) Date: Tue, 21 Apr 2009 17:21:01 -0000 Subject: [llvm-commits] [llvm] r69684 - /llvm/trunk/test/FrontendC++/2009-04-21-DtorNames-dbg.cpp Message-ID: <200904211721.n3LHL2b7029016@zion.cs.uiuc.edu> Author: dpatel Date: Tue Apr 21 12:21:01 2009 New Revision: 69684 URL: http://llvm.org/viewvc/llvm-project?rev=69684&view=rev Log: Test case for revision 69683. Added: llvm/trunk/test/FrontendC++/2009-04-21-DtorNames-dbg.cpp Added: llvm/trunk/test/FrontendC++/2009-04-21-DtorNames-dbg.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC%2B%2B/2009-04-21-DtorNames-dbg.cpp?rev=69684&view=auto ============================================================================== --- llvm/trunk/test/FrontendC++/2009-04-21-DtorNames-dbg.cpp (added) +++ llvm/trunk/test/FrontendC++/2009-04-21-DtorNames-dbg.cpp Tue Apr 21 12:21:01 2009 @@ -0,0 +1,32 @@ +// RUN: %llvmgcc -c -g %s -o - | llc -fast -f -o %t.s +// RUN: %compile_c %t.s -o %t.o +// PR4025 + +template class vector +{ +public: + ~vector () + { + } +}; + +class Foo +{ + ~Foo(); + class FooImpl *impl_; +}; + +namespace { + class Bar; +} + +class FooImpl +{ + vector thing; +}; + +Foo::~Foo() +{ + delete impl_; +} + From bob.wilson at apple.com Tue Apr 21 12:27:55 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 21 Apr 2009 17:27:55 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r69685 - /llvm-gcc-4.2/trunk/config.guess Message-ID: <200904211727.n3LHRtEV029268@zion.cs.uiuc.edu> Author: bwilson Date: Tue Apr 21 12:27:55 2009 New Revision: 69685 URL: http://llvm.org/viewvc/llvm-project?rev=69685&view=rev Log: pr4005: Detect ARM/Linux system with EABI based on whether the default compiler defines __ARM_EABI__. Modified: llvm-gcc-4.2/trunk/config.guess Modified: llvm-gcc-4.2/trunk/config.guess URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/config.guess?rev=69685&r1=69684&r2=69685&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/config.guess (original) +++ llvm-gcc-4.2/trunk/config.guess Tue Apr 21 12:27:55 2009 @@ -829,7 +829,21 @@ echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef eabi + #if defined(__ARM_EABI__) + ARMABI=eabi + #else + ARMABI= + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^ARMABI/{ + s: ::g + p + }'`" + echo ${UNAME_MACHINE}-unknown-linux-gnu${ARMABI} exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu From anton at korobeynikov.info Tue Apr 21 12:36:07 2009 From: anton at korobeynikov.info (Anton Korobeynikov) Date: Tue, 21 Apr 2009 21:36:07 +0400 Subject: [llvm-commits] [llvm-gcc-4.2] r69685 - /llvm-gcc-4.2/trunk/config.guess In-Reply-To: <200904211727.n3LHRtEV029268@zion.cs.uiuc.edu> References: <200904211727.n3LHRtEV029268@zion.cs.uiuc.edu> Message-ID: Hi, Bob > + ? ? ? ? ? ? ? p > + ? ? ? ? ? }'`" > + ? ? ? echo ${UNAME_MACHINE}-unknown-linux-gnu${ARMABI} Shouldn't here be "LLVM LOCAL" markers? -- With best regards, Anton Korobeynikov Faculty of Mathematics and Mechanics, Saint Petersburg State University From isanbard at gmail.com Tue Apr 21 13:14:24 2009 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 21 Apr 2009 18:14:24 -0000 Subject: [llvm-commits] [llvm] r69690 - /llvm/tags/Apple/llvmCore-2105.2/ Message-ID: <200904211814.n3LIEOOh030874@zion.cs.uiuc.edu> Author: void Date: Tue Apr 21 13:14:23 2009 New Revision: 69690 URL: http://llvm.org/viewvc/llvm-project?rev=69690&view=rev Log: Creating llvmCore-2105.2 from llvmCore-2105.1. Added: llvm/tags/Apple/llvmCore-2105.2/ - copied from r69689, llvm/tags/Apple/llvmCore-2105.1/ From isanbard at gmail.com Tue Apr 21 13:15:07 2009 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 21 Apr 2009 18:15:07 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r69691 - /llvm-gcc-4.2/tags/Apple/llvmgcc42-2105.2/ Message-ID: <200904211815.n3LIF7No030907@zion.cs.uiuc.edu> Author: void Date: Tue Apr 21 13:15:07 2009 New Revision: 69691 URL: http://llvm.org/viewvc/llvm-project?rev=69691&view=rev Log: Creating llvmgcc42-2105.2 from llvmgcc42-2105.1. Added: llvm-gcc-4.2/tags/Apple/llvmgcc42-2105.2/ - copied from r69690, llvm-gcc-4.2/tags/Apple/llvmgcc42-2105.1/ From bob.wilson at apple.com Tue Apr 21 13:17:32 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 21 Apr 2009 11:17:32 -0700 Subject: [llvm-commits] [llvm-gcc-4.2] r69685 - /llvm-gcc-4.2/trunk/config.guess In-Reply-To: References: <200904211727.n3LHRtEV029268@zion.cs.uiuc.edu> Message-ID: <0306EB3D-930A-4D3E-A452-DA910D09B7F6@apple.com> On Apr 21, 2009, at 10:36 AM, Anton Korobeynikov wrote: > Hi, Bob > >> + p >> + }'`" >> + echo ${UNAME_MACHINE}-unknown-linux-gnu${ARMABI} > Shouldn't here be "LLVM LOCAL" markers? Yes. Thanks for reminding me. From bob.wilson at apple.com Tue Apr 21 13:20:34 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 21 Apr 2009 18:20:34 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r69692 - /llvm-gcc-4.2/trunk/config.guess Message-ID: <200904211820.n3LIKYsl031065@zion.cs.uiuc.edu> Author: bwilson Date: Tue Apr 21 13:20:34 2009 New Revision: 69692 URL: http://llvm.org/viewvc/llvm-project?rev=69692&view=rev Log: Add LLVM LOCAL markers. Modified: llvm-gcc-4.2/trunk/config.guess Modified: llvm-gcc-4.2/trunk/config.guess URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/config.guess?rev=69692&r1=69691&r2=69692&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/config.guess (original) +++ llvm-gcc-4.2/trunk/config.guess Tue Apr 21 13:20:34 2009 @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, # Inc. -timestamp='2006-07-02' +timestamp='2009-04-21' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -829,6 +829,7 @@ echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) + # LLVM LOCAL begin pr4005 eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef eabi @@ -844,6 +845,7 @@ p }'`" echo ${UNAME_MACHINE}-unknown-linux-gnu${ARMABI} + # LLVM LOCAL end pr4005 exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu From isanbard at gmail.com Tue Apr 21 13:29:45 2009 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 21 Apr 2009 18:29:45 -0000 Subject: [llvm-commits] [llvm] r69693 - /llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp Message-ID: <200904211829.n3LITjhE031349@zion.cs.uiuc.edu> Author: void Date: Tue Apr 21 13:29:45 2009 New Revision: 69693 URL: http://llvm.org/viewvc/llvm-project?rev=69693&view=rev Log: --- Merging r69314 into '.': U lib/ExecutionEngine/JIT/JIT.cpp Merge in this fix into llvmCore-2105.2. Modified: llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp Modified: llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp?rev=69693&r1=69692&r2=69693&view=diff ============================================================================== --- llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp (original) +++ llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp Tue Apr 21 13:29:45 2009 @@ -231,11 +231,9 @@ // The key is created on demand, and libgcc creates it the first time an // exception occurs. Since we need the key to register frames, we create // it now. - if (!LOI) { - LOI = (LibgccObjectInfo*)malloc(sizeof(struct LibgccObjectInfo)); - _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, - LOI); - } + if (!LOI) + LOI = (LibgccObjectInfo*)calloc(sizeof(struct LibgccObjectInfo), 1); + _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, LOI); InstallExceptionTableRegister(DarwinRegisterFrame); #else InstallExceptionTableRegister(__register_frame); From foldr at codedgers.com Tue Apr 21 14:46:10 2009 From: foldr at codedgers.com (Mikhail Glushenkov) Date: Tue, 21 Apr 2009 19:46:10 -0000 Subject: [llvm-commits] [llvm] r69700 - in /llvm/trunk: Makefile.rules autoconf/configure.ac configure tools/llvmc/plugins/Base/Base.td tools/llvmc/plugins/Base/Base.td.in Message-ID: <200904211946.n3LJkBZv001687@zion.cs.uiuc.edu> Author: foldr Date: Tue Apr 21 14:46:10 2009 New Revision: 69700 URL: http://llvm.org/viewvc/llvm-project?rev=69700&view=rev Log: Support --with-llvmgccdir and friends in llvmc, take 2. Should now work when building with objdir != srcdir and when llvm-gcc is not available. Thanks to Duncan Sands for testing and advice! Added: llvm/trunk/tools/llvmc/plugins/Base/Base.td.in - copied, changed from r69665, llvm/trunk/tools/llvmc/plugins/Base/Base.td Removed: llvm/trunk/tools/llvmc/plugins/Base/Base.td Modified: llvm/trunk/Makefile.rules llvm/trunk/autoconf/configure.ac llvm/trunk/configure Modified: llvm/trunk/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/Makefile.rules?rev=69700&r1=69699&r2=69700&view=diff ============================================================================== --- llvm/trunk/Makefile.rules (original) +++ llvm/trunk/Makefile.rules Tue Apr 21 14:46:10 2009 @@ -1466,7 +1466,8 @@ ifdef LLVMC_BUILD_AUTOGENERATED_INC -LLVMCPluginSrc := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td)) +LLVMCPluginSrc := $(sort $(strip $(wildcard $(PROJ_SRC_DIR)/*.td)) \ + $(strip $(wildcard $(PROJ_OBJ_DIR)/*.td))) TDFiles := $(LLVMCPluginSrc) \ $(strip $(wildcard $(LLVM_SRC_ROOT)/include/llvm/CompilerDriver/*.td)) Modified: llvm/trunk/autoconf/configure.ac URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/autoconf/configure.ac?rev=69700&r1=69699&r2=69700&view=diff ============================================================================== --- llvm/trunk/autoconf/configure.ac (original) +++ llvm/trunk/autoconf/configure.ac Tue Apr 21 14:46:10 2009 @@ -472,6 +472,14 @@ LLVMGXX=$with_llvmgxx WITH_LLVMGCCDIR="",) +if test -n "$LLVMGCC"; then + LLVMGCCCOMMAND="$LLVMGCC" +fi + +if test -n "$LLVMGXX"; then + LLVMGXXCOMMAND="$LLVMGXX" +fi + if test -n "$LLVMGCC" && test -z "$LLVMGXX"; then AC_MSG_ERROR([Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used]); fi @@ -663,22 +671,33 @@ [Define if dlopen(0) will open the symbols of the program]) fi + if test "$WITH_LLVMGCCDIR" = "default" ; then LLVMGCC="llvm-gcc${EXEEXT}" LLVMGXX="llvm-g++${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + LLVMGXXCOMMAND="$LLVMGXX" + AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND) + AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND) AC_PATH_PROG(LLVMGCC, $LLVMGCC, []) AC_PATH_PROG(LLVMGXX, $LLVMGXX, []) else if test -z "$LLVMGCC"; then LLVMGCC="$WITH_LLVMGCCDIR/bin/llvm-gcc${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" fi if test -z "$LLVMGXX"; then LLVMGXX="$WITH_LLVMGCCDIR/bin/llvm-g++${EXEEXT}" + LLVMGXXCOMMAND="$LLVMGXX" fi + AC_SUBST(LLVMGCC,$LLVMGCC) AC_SUBST(LLVMGXX,$LLVMGXX) + AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND) + AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND) fi + AC_MSG_CHECKING([tool compatibility]) dnl Ensure that compilation tools are GCC or a GNU compatible compiler such as @@ -1065,6 +1084,9 @@ dnl Configure doxygen's configuration file AC_CONFIG_FILES([docs/doxygen.cfg]) +dnl Configure llvmc's Base plugin +AC_CONFIG_FILES([tools/llvmc/plugins/Base/Base.td]) + dnl Do the first stage of configuration for llvm-config.in. AC_CONFIG_FILES([tools/llvm-config/llvm-config.in]) Modified: llvm/trunk/configure URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/configure?rev=69700&r1=69699&r2=69700&view=diff ============================================================================== --- llvm/trunk/configure (original) +++ llvm/trunk/configure Tue Apr 21 14:46:10 2009 @@ -899,6 +899,8 @@ LIBTOOL LLVMGCC LLVMGXX +LLVMGCCCOMMAND +LLVMGXXCOMMAND USE_UDIS86 HAVE_PTHREAD HUGE_VAL_SANITY @@ -5003,6 +5005,13 @@ WITH_LLVMGCCDIR="" fi +if test -n "$LLVMGCC"; then + LLVMGCCCOMMAND="$LLVMGCC" +fi + +if test -n "$LLVMGXX"; then + LLVMGXXCOMMAND="$LLVMGXX" +fi if test -n "$LLVMGCC" && test -z "$LLVMGXX"; then { { echo "$as_me:$LINENO: error: Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used" >&5 @@ -26810,6 +26819,13 @@ if test "$WITH_LLVMGCCDIR" = "default" ; then LLVMGCC="llvm-gcc${EXEEXT}" LLVMGXX="llvm-g++${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + LLVMGXXCOMMAND="$LLVMGXX" + + LLVMGCCCOMMAND=$LLVMGCCCOMMAND + + LLVMGXXCOMMAND=$LLVMGXXCOMMAND + # Extract the first word of "$LLVMGCC", so it can be a program name with args. set dummy $LLVMGCC; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 @@ -26893,16 +26909,24 @@ else if test -z "$LLVMGCC"; then LLVMGCC="$WITH_LLVMGCCDIR/bin/llvm-gcc${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" fi if test -z "$LLVMGXX"; then LLVMGXX="$WITH_LLVMGCCDIR/bin/llvm-g++${EXEEXT}" + LLVMGXXCOMMAND="$LLVMGXX" fi + LLVMGCC=$LLVMGCC LLVMGXX=$LLVMGXX + LLVMGCCCOMMAND=$LLVMGCCCOMMAND + + LLVMGXXCOMMAND=$LLVMGXXCOMMAND + fi + { echo "$as_me:$LINENO: checking tool compatibility" >&5 echo $ECHO_N "checking tool compatibility... $ECHO_C" >&6; } @@ -34003,6 +34027,9 @@ ac_config_files="$ac_config_files docs/doxygen.cfg" +ac_config_files="$ac_config_files tools/llvmc/plugins/Base/Base.td" + + ac_config_files="$ac_config_files tools/llvm-config/llvm-config.in" @@ -34617,6 +34644,7 @@ "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;; "llvm.spec") CONFIG_FILES="$CONFIG_FILES llvm.spec" ;; "docs/doxygen.cfg") CONFIG_FILES="$CONFIG_FILES docs/doxygen.cfg" ;; + "tools/llvmc/plugins/Base/Base.td") CONFIG_FILES="$CONFIG_FILES tools/llvmc/plugins/Base/Base.td" ;; "tools/llvm-config/llvm-config.in") CONFIG_FILES="$CONFIG_FILES tools/llvm-config/llvm-config.in" ;; "setup") CONFIG_COMMANDS="$CONFIG_COMMANDS setup" ;; "Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile" ;; @@ -34878,6 +34906,8 @@ LIBTOOL!$LIBTOOL$ac_delim LLVMGCC!$LLVMGCC$ac_delim LLVMGXX!$LLVMGXX$ac_delim +LLVMGCCCOMMAND!$LLVMGCCCOMMAND$ac_delim +LLVMGXXCOMMAND!$LLVMGXXCOMMAND$ac_delim USE_UDIS86!$USE_UDIS86$ac_delim HAVE_PTHREAD!$HAVE_PTHREAD$ac_delim HUGE_VAL_SANITY!$HUGE_VAL_SANITY$ac_delim @@ -34911,7 +34941,7 @@ LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 77; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 79; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 Removed: llvm/trunk/tools/llvmc/plugins/Base/Base.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc/plugins/Base/Base.td?rev=69699&view=auto ============================================================================== --- llvm/trunk/tools/llvmc/plugins/Base/Base.td (original) +++ llvm/trunk/tools/llvmc/plugins/Base/Base.td (removed) @@ -1,202 +0,0 @@ -//===- Base.td - LLVMC2 toolchain descriptions -------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains compilation graph description used by llvmc2. -// -//===----------------------------------------------------------------------===// - -include "llvm/CompilerDriver/Common.td" - -// Options - -def OptList : OptionList<[ - (switch_option "emit-llvm", - (help "Emit LLVM .ll files instead of native object files")), - (switch_option "E", - (help "Stop after the preprocessing stage, do not run the compiler")), - (switch_option "fsyntax-only", - (help "Stop after checking the input for syntax errors")), - (switch_option "opt", - (help "Enable opt")), - (switch_option "S", - (help "Stop after compilation, do not assemble")), - (switch_option "c", - (help "Compile and assemble, but do not link")), - (switch_option "pthread", - (help "Enable threads")), - (parameter_option "linker", - (help "Choose linker (possible values: gcc, g++)")), - (parameter_list_option "include", - (help "Include the named file prior to preprocessing")), - (prefix_list_option "I", - (help "Add a directory to include path")), - (prefix_list_option "Wa,", - (help "Pass options to assembler")), - (prefix_list_option "Wllc,", - (help "Pass options to llc")), - (prefix_list_option "L", - (help "Add a directory to link path")), - (prefix_list_option "l", - (help "Search a library when linking")), - (prefix_list_option "Wl,", - (help "Pass options to linker")), - (prefix_list_option "Wo,", - (help "Pass options to opt")) -]>; - -// Tools - -class llvm_gcc_based : Tool< -[(in_language in_lang), - (out_language "llvm-bitcode"), - (output_suffix "bc"), - (cmd_line (case - (switch_on "E"), - (case (not_empty "o"), - !strconcat(cmd_prefix, " -E $INFILE -o $OUTFILE"), - (default), - !strconcat(cmd_prefix, " -E $INFILE")), - (switch_on "fsyntax-only"), - !strconcat(cmd_prefix, " -fsyntax-only $INFILE"), - (and (switch_on "S"), (switch_on "emit-llvm")), - !strconcat(cmd_prefix, " -S $INFILE -o $OUTFILE -emit-llvm"), - (default), - !strconcat(cmd_prefix, " -c $INFILE -o $OUTFILE -emit-llvm"))), - (actions - (case - (switch_on "E"), [(stop_compilation), (output_suffix E_ext)], - (and (switch_on "emit-llvm"), (switch_on "S")), - [(output_suffix "ll"), (stop_compilation)], - (and (switch_on "emit-llvm"), (switch_on "c")), (stop_compilation), - (switch_on "fsyntax-only"), (stop_compilation), - (not_empty "include"), (forward "include"), - (not_empty "I"), (forward "I"))), - (sink) -]>; - -def llvm_gcc_c : llvm_gcc_based<"llvm-gcc -x c", "c", "i">; -def llvm_gcc_cpp : llvm_gcc_based<"llvm-g++ -x c++", "c++", "i">; -def llvm_gcc_m : llvm_gcc_based<"llvm-gcc -x objective-c", "objective-c", "mi">; -def llvm_gcc_mxx : llvm_gcc_based<"llvm-gcc -x objective-c++", - "objective-c++", "mi">; - -def opt : Tool< -[(in_language "llvm-bitcode"), - (out_language "llvm-bitcode"), - (output_suffix "bc"), - (actions (case (not_empty "Wo,"), (unpack_values "Wo,"))), - (cmd_line "opt -f $INFILE -o $OUTFILE") -]>; - -def llvm_as : Tool< -[(in_language "llvm-assembler"), - (out_language "llvm-bitcode"), - (output_suffix "bc"), - (cmd_line "llvm-as $INFILE -o $OUTFILE") -]>; - -def llvm_gcc_assembler : Tool< -[(in_language "assembler"), - (out_language "object-code"), - (output_suffix "o"), - (cmd_line "llvm-gcc -c -x assembler $INFILE -o $OUTFILE"), - (actions (case - (switch_on "c"), (stop_compilation), - (not_empty "Wa,"), (unpack_values "Wa,"))) -]>; - -def llc : Tool< -[(in_language "llvm-bitcode"), - (out_language "assembler"), - (output_suffix "s"), - (cmd_line "llc -f $INFILE -o $OUTFILE"), - (actions (case - (switch_on "S"), (stop_compilation), - (not_empty "Wllc,"), (unpack_values "Wllc,"))) -]>; - -// Base class for linkers -class llvm_gcc_based_linker : Tool< -[(in_language "object-code"), - (out_language "executable"), - (output_suffix "out"), - (cmd_line !strconcat(cmd_prefix, " $INFILE -o $OUTFILE")), - (join), - (actions (case - (switch_on "pthread"), (append_cmd "-lpthread"), - (not_empty "L"), (forward "L"), - (not_empty "l"), (forward "l"), - (not_empty "Wl,"), (unpack_values "Wl,"))) -]>; - -// Default linker -def llvm_gcc_linker : llvm_gcc_based_linker<"llvm-gcc">; -// Alternative linker for C++ -def llvm_gcc_cpp_linker : llvm_gcc_based_linker<"llvm-g++">; - -// Language map - -def LanguageMap : LanguageMap< - [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>, - LangToSuffixes<"c", ["c"]>, - LangToSuffixes<"c-cpp-output", ["i"]>, - LangToSuffixes<"objective-c-cpp-output", ["mi"]>, - LangToSuffixes<"objective-c++", ["mm"]>, - LangToSuffixes<"objective-c", ["m"]>, - LangToSuffixes<"assembler", ["s"]>, - LangToSuffixes<"assembler-with-cpp", ["S"]>, - LangToSuffixes<"llvm-assembler", ["ll"]>, - LangToSuffixes<"llvm-bitcode", ["bc"]>, - LangToSuffixes<"object-code", ["o"]>, - LangToSuffixes<"executable", ["out"]> - ]>; - -// Compilation graph - -def CompilationGraph : CompilationGraph<[ - Edge<"root", "llvm_gcc_c">, - Edge<"root", "llvm_gcc_assembler">, - Edge<"root", "llvm_gcc_cpp">, - Edge<"root", "llvm_gcc_m">, - Edge<"root", "llvm_gcc_mxx">, - Edge<"root", "llvm_as">, - - Edge<"llvm_gcc_c", "llc">, - Edge<"llvm_gcc_cpp", "llc">, - Edge<"llvm_gcc_m", "llc">, - Edge<"llvm_gcc_mxx", "llc">, - Edge<"llvm_as", "llc">, - - OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"), (inc_weight))>, - OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"), (inc_weight))>, - OptionalEdge<"llvm_gcc_m", "opt", (case (switch_on "opt"), (inc_weight))>, - OptionalEdge<"llvm_gcc_mxx", "opt", (case (switch_on "opt"), (inc_weight))>, - OptionalEdge<"llvm_as", "opt", (case (switch_on "opt"), (inc_weight))>, - Edge<"opt", "llc">, - - Edge<"llc", "llvm_gcc_assembler">, - Edge<"llvm_gcc_assembler", "llvm_gcc_linker">, - OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker", - (case - (or (input_languages_contain "c++"), - (input_languages_contain "objective-c++")), - (inc_weight), - (or (parameter_equals "linker", "g++"), - (parameter_equals "linker", "c++")), (inc_weight))>, - - - Edge<"root", "llvm_gcc_linker">, - OptionalEdge<"root", "llvm_gcc_cpp_linker", - (case - (or (input_languages_contain "c++"), - (input_languages_contain "objective-c++")), - (inc_weight), - (or (parameter_equals "linker", "g++"), - (parameter_equals "linker", "c++")), (inc_weight))> - ]>; Copied: llvm/trunk/tools/llvmc/plugins/Base/Base.td.in (from r69665, llvm/trunk/tools/llvmc/plugins/Base/Base.td) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc/plugins/Base/Base.td.in?p2=llvm/trunk/tools/llvmc/plugins/Base/Base.td.in&p1=llvm/trunk/tools/llvmc/plugins/Base/Base.td&r1=69665&r2=69700&rev=69700&view=diff ============================================================================== --- llvm/trunk/tools/llvmc/plugins/Base/Base.td (original) +++ llvm/trunk/tools/llvmc/plugins/Base/Base.td.in Tue Apr 21 14:46:10 2009 @@ -80,10 +80,10 @@ (sink) ]>; -def llvm_gcc_c : llvm_gcc_based<"llvm-gcc -x c", "c", "i">; -def llvm_gcc_cpp : llvm_gcc_based<"llvm-g++ -x c++", "c++", "i">; -def llvm_gcc_m : llvm_gcc_based<"llvm-gcc -x objective-c", "objective-c", "mi">; -def llvm_gcc_mxx : llvm_gcc_based<"llvm-gcc -x objective-c++", +def llvm_gcc_c : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x c", "c", "i">; +def llvm_gcc_cpp : llvm_gcc_based<"@LLVMGXXCOMMAND@ -x c++", "c++", "i">; +def llvm_gcc_m : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c", "objective-c", "mi">; +def llvm_gcc_mxx : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c++", "objective-c++", "mi">; def opt : Tool< @@ -105,7 +105,7 @@ [(in_language "assembler"), (out_language "object-code"), (output_suffix "o"), - (cmd_line "llvm-gcc -c -x assembler $INFILE -o $OUTFILE"), + (cmd_line "@LLVMGCCCOMMAND@ -c -x assembler $INFILE -o $OUTFILE"), (actions (case (switch_on "c"), (stop_compilation), (not_empty "Wa,"), (unpack_values "Wa,"))) @@ -136,9 +136,9 @@ ]>; // Default linker -def llvm_gcc_linker : llvm_gcc_based_linker<"llvm-gcc">; +def llvm_gcc_linker : llvm_gcc_based_linker<"@LLVMGCCCOMMAND@">; // Alternative linker for C++ -def llvm_gcc_cpp_linker : llvm_gcc_based_linker<"llvm-g++">; +def llvm_gcc_cpp_linker : llvm_gcc_based_linker<"@LLVMGXXCOMMAND@">; // Language map From gohman at apple.com Tue Apr 21 15:18:37 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 21 Apr 2009 20:18:37 -0000 Subject: [llvm-commits] [llvm] r69704 - in /llvm/trunk: lib/Analysis/ScalarEvolution.cpp test/Analysis/ScalarEvolution/sext-inreg.ll Message-ID: <200904212018.n3LKIb3I002910@zion.cs.uiuc.edu> Author: djg Date: Tue Apr 21 15:18:36 2009 New Revision: 69704 URL: http://llvm.org/viewvc/llvm-project?rev=69704&view=rev Log: When turning (ashr(shl(x, n), n)) into sext(trunc(x)), the width of the type to truncate to should be the number of bits of the value that are preserved, not the number that are clobbered with sign-extension. This fixes regressions in ldecod. Added: llvm/trunk/test/Analysis/ScalarEvolution/sext-inreg.ll Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69704&r1=69703&r2=69704&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Tue Apr 21 15:18:36 2009 @@ -2015,7 +2015,7 @@ if (Instruction *L = dyn_cast(U->getOperand(0))) if (L->getOpcode() == Instruction::Shl && L->getOperand(1) == U->getOperand(1)) { - uint64_t Amt = CI->getZExtValue(); + uint64_t Amt = getTypeSizeInBits(U->getType()) - CI->getZExtValue(); return SE.getSignExtendExpr(SE.getTruncateExpr(getSCEV(L->getOperand(0)), IntegerType::get(Amt)), Added: llvm/trunk/test/Analysis/ScalarEvolution/sext-inreg.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/sext-inreg.ll?rev=69704&view=auto ============================================================================== --- llvm/trunk/test/Analysis/ScalarEvolution/sext-inreg.ll (added) +++ llvm/trunk/test/Analysis/ScalarEvolution/sext-inreg.ll Tue Apr 21 15:18:36 2009 @@ -0,0 +1,29 @@ +; RUN: llvm-as < %s | opt -analyze -scalar-evolution -disable-output \ +; RUN: | grep {signextend \{0,+,199\} to i64} | count 2 + +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" +target triple = "i386-apple-darwin9.6" + +define i64 @foo(i64* nocapture %x, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 ; [#uses=1] + br i1 %t0, label %bb, label %return + +bb: ; preds = %bb, %entry + %i.01 = phi i64 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=2] + %t1 = shl i64 %i.01, 7 ; [#uses=1] + %t2 = ashr i64 %t1, 7 ; [#uses=1] + %s1 = shl i64 %i.01, 5 ; [#uses=1] + %s2 = ashr i64 %s1, 5 ; [#uses=1] + %t3 = getelementptr i64* %x, i64 %i.01 ; [#uses=1] + store i64 0, i64* %t3, align 1 + %indvar.next = add i64 %i.01, 199 ; [#uses=2] + %exitcond = icmp eq i64 %indvar.next, %n ; [#uses=1] + br i1 %exitcond, label %return, label %bb + +return: ; preds = %bb, %entry + %p = phi i64 [ 0, %entry ], [ %t2, %bb ] + %q = phi i64 [ 0, %entry ], [ %s2, %bb ] + %v = xor i64 %p, %q + ret i64 %v +} From evan.cheng at apple.com Tue Apr 21 17:46:52 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 21 Apr 2009 22:46:52 -0000 Subject: [llvm-commits] [llvm] r69743 - in /llvm/trunk: include/llvm/CodeGen/LiveIntervalAnalysis.h lib/CodeGen/LiveIntervalAnalysis.cpp lib/CodeGen/RegAllocLinearScan.cpp lib/CodeGen/RegAllocPBQP.cpp lib/CodeGen/Spiller.cpp lib/CodeGen/Spiller.h test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll Message-ID: <200904212246.n3LMkq68008211@zion.cs.uiuc.edu> Author: evancheng Date: Tue Apr 21 17:46:52 2009 New Revision: 69743 URL: http://llvm.org/viewvc/llvm-project?rev=69743&view=rev Log: It has finally happened. Spiller is now using live interval info. This fixes a very subtle bug. vr defined by an implicit_def is allowed overlap with any register since it doesn't actually modify anything. However, if it's used as a two-address use, its live range can be extended and it can be spilled. The spiller must take care not to emit a reload for the vn number that's defined by the implicit_def. This is both a correctness and performance issue. Added: llvm/trunk/test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll Modified: llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp llvm/trunk/lib/CodeGen/Spiller.cpp llvm/trunk/lib/CodeGen/Spiller.h Modified: llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h?rev=69743&r1=69742&r2=69743&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h (original) +++ llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h Tue Apr 21 17:46:52 2009 @@ -300,9 +300,9 @@ r2iMap_.erase(I); } - /// isRemoved - returns true if the specified machine instr has been - /// removed. - bool isRemoved(MachineInstr* instr) const { + /// isNotInMIMap - returns true if the specified machine instr has been + /// removed or was never entered in the map. + bool isNotInMIMap(MachineInstr* instr) const { return !mi2iMap_.count(instr); } Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=69743&r1=69742&r2=69743&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Tue Apr 21 17:46:52 2009 @@ -1304,7 +1304,7 @@ // Update stack slot spill weight if we are splitting. float Weight = getSpillWeight(HasDef, HasUse, loopDepth); - if (!TrySplit) + if (!TrySplit) SSWeight += Weight; // Create a new virtual register for the spill interval. @@ -1338,7 +1338,7 @@ HasUse = false; HasDef = false; CanFold = false; - if (isRemoved(MI)) { + if (isNotInMIMap(MI)) { SSWeight -= Weight; break; } @@ -1393,7 +1393,7 @@ if (DefIsReMat && ImpUse) MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true)); - // create a new register interval for this spill / remat. + // Create a new register interval for this spill / remat. LiveInterval &nI = getOrCreateInterval(NewVReg); if (CreatedNewVReg) { NewLIs.push_back(&nI); Modified: llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp?rev=69743&r1=69742&r2=69743&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Tue Apr 21 17:46:52 2009 @@ -345,7 +345,7 @@ linearScan(); // Rewrite spill code and update the PhysRegsUsed set. - spiller_->runOnMachineFunction(*mf_, *vrm_); + spiller_->runOnMachineFunction(*mf_, *vrm_, li_); assert(unhandled_.empty() && "Unhandled live intervals remain!"); fixed_.clear(); Modified: llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp?rev=69743&r1=69742&r2=69743&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp Tue Apr 21 17:46:52 2009 @@ -854,7 +854,7 @@ // Run spiller std::auto_ptr spiller(createSpiller()); - spiller->runOnMachineFunction(*mf, *vrm); + spiller->runOnMachineFunction(*mf, *vrm, lis); return true; } Modified: llvm/trunk/lib/CodeGen/Spiller.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Spiller.cpp?rev=69743&r1=69742&r2=69743&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/Spiller.cpp (original) +++ llvm/trunk/lib/CodeGen/Spiller.cpp Tue Apr 21 17:46:52 2009 @@ -23,6 +23,7 @@ STATISTIC(NumStores , "Number of stores added"); STATISTIC(NumPSpills , "Number of physical register spills"); STATISTIC(NumOmitted , "Number of reloads omited"); +STATISTIC(NumAvoided , "Number of reloads deemed unnecessary"); STATISTIC(NumCopified, "Number of available reloads turned into copies"); STATISTIC(NumReMats , "Number of re-materialization"); STATISTIC(NumLoads , "Number of loads added"); @@ -50,7 +51,8 @@ Spiller::~Spiller() {} -bool SimpleSpiller::runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM) { +bool SimpleSpiller::runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs) { DOUT << "********** REWRITE MACHINE CODE **********\n"; DOUT << "********** Function: " << MF.getFunction()->getName() << '\n'; const TargetMachine &TM = MF.getTarget(); @@ -521,7 +523,8 @@ // Local Spiller Implementation // // ***************************** // -bool LocalSpiller::runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM) { +bool LocalSpiller::runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs) { RegInfo = &MF.getRegInfo(); TRI = MF.getTarget().getRegisterInfo(); TII = MF.getTarget().getInstrInfo(); @@ -555,7 +558,7 @@ DFI != E; ++DFI) { MachineBasicBlock *MBB = *DFI; if (!EarlyVisited.count(MBB)) - RewriteMBB(*MBB, VRM, Spills, RegKills, KillOps); + RewriteMBB(*MBB, VRM, LIs, Spills, RegKills, KillOps); // If this MBB is the only predecessor of a successor. Keep the // availability information and visit it next. @@ -571,7 +574,7 @@ MBB = SinglePredSuccs[0]; if (!Visited.count(MBB) && EarlyVisited.insert(MBB)) { Spills.AddAvailableRegsToLiveIn(*MBB, RegKills, KillOps); - RewriteMBB(*MBB, VRM, Spills, RegKills, KillOps); + RewriteMBB(*MBB, VRM, LIs, Spills, RegKills, KillOps); } } } while (MBB); @@ -1109,6 +1112,7 @@ /// rewriteMBB - Keep track of which spills are available even after the /// register allocator is done with them. If possible, avid reloading vregs. void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM, + LiveIntervals *LIs, AvailableSpills &Spills, BitVector &RegKills, std::vector &KillOps) { DOUT << "\n**** Local spiller rewriting MBB '" @@ -1339,6 +1343,22 @@ if (!MO.isUse()) continue; // Handle defs in the loop below (handle use&def here though) + bool AvoidReload = false; + if (LIs->hasInterval(VirtReg)) { + LiveInterval &LI = LIs->getInterval(VirtReg); + if (!LI.liveAt(LIs->getUseIndex(LI.beginNumber()))) + // Must be defined by an implicit def. It should not be spilled. Note, + // this is for correctness reason. e.g. + // 8 %reg1024 = IMPLICIT_DEF + // 12 %reg1024 = INSERT_SUBREG %reg1024, %reg1025, 2 + // The live range [12, 14) are not part of the r1024 live interval since + // it's defined by an implicit def. It will not conflicts with live + // interval of r1025. Now suppose both registers are spilled, you can + // easily see a situation where both registers are reloaded before + // the INSERT_SUBREG and both target registers that would overlap. + AvoidReload = true; + } + bool DoReMat = VRM.isReMaterialized(VirtReg); int SSorRMId = DoReMat ? VRM.getReMatId(VirtReg) : VRM.getStackSlot(VirtReg); @@ -1357,14 +1377,14 @@ // = EXTRACT_SUBREG fi#1 // fi#1 is available in EDI, but it cannot be reused because it's not in // the right register file. - if (PhysReg && + if (PhysReg && !AvoidReload && (SubIdx || MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)) { const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); if (!RC->contains(PhysReg)) PhysReg = 0; } - if (PhysReg) { + if (PhysReg && !AvoidReload) { // This spilled operand might be part of a two-address operand. If this // is the case, then changing it will necessarily require changing the // def part of the instruction as well. However, in some cases, we @@ -1513,34 +1533,39 @@ RegInfo->setPhysRegUsed(PhysReg); ReusedOperands.markClobbered(PhysReg); - if (DoReMat) { - ReMaterialize(MBB, MII, PhysReg, VirtReg, TII, TRI, VRM); - } else { - const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); - TII->loadRegFromStackSlot(MBB, &MI, PhysReg, SSorRMId, RC); - MachineInstr *LoadMI = prior(MII); - VRM.addSpillSlotUse(SSorRMId, LoadMI); - ++NumLoads; - } - // This invalidates PhysReg. - Spills.ClobberPhysReg(PhysReg); - - // Any stores to this stack slot are not dead anymore. - if (!DoReMat) - MaybeDeadStores[SSorRMId] = NULL; - Spills.addAvailable(SSorRMId, PhysReg); - // Assumes this is the last use. IsKill will be unset if reg is reused - // unless it's a two-address operand. - if (!MI.isRegTiedToDefOperand(i) && - KilledMIRegs.count(VirtReg) == 0) { - MI.getOperand(i).setIsKill(); - KilledMIRegs.insert(VirtReg); + if (AvoidReload) + ++NumAvoided; + else { + if (DoReMat) { + ReMaterialize(MBB, MII, PhysReg, VirtReg, TII, TRI, VRM); + } else { + const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); + TII->loadRegFromStackSlot(MBB, &MI, PhysReg, SSorRMId, RC); + MachineInstr *LoadMI = prior(MII); + VRM.addSpillSlotUse(SSorRMId, LoadMI); + ++NumLoads; + } + // This invalidates PhysReg. + Spills.ClobberPhysReg(PhysReg); + + // Any stores to this stack slot are not dead anymore. + if (!DoReMat) + MaybeDeadStores[SSorRMId] = NULL; + Spills.addAvailable(SSorRMId, PhysReg); + // Assumes this is the last use. IsKill will be unset if reg is reused + // unless it's a two-address operand. + if (!MI.isRegTiedToDefOperand(i) && + KilledMIRegs.count(VirtReg) == 0) { + MI.getOperand(i).setIsKill(); + KilledMIRegs.insert(VirtReg); + } + + UpdateKills(*prior(MII), RegKills, KillOps, TRI); + DOUT << '\t' << *prior(MII); } unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; MI.getOperand(i).setReg(RReg); MI.getOperand(i).setSubReg(0); - UpdateKills(*prior(MII), RegKills, KillOps, TRI); - DOUT << '\t' << *prior(MII); } // Ok - now we can remove stores that have been confirmed dead. Modified: llvm/trunk/lib/CodeGen/Spiller.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Spiller.h?rev=69743&r1=69742&r2=69743&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/Spiller.h (original) +++ llvm/trunk/lib/CodeGen/Spiller.h Tue Apr 21 17:46:52 2009 @@ -17,6 +17,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Streams.h" #include "llvm/Function.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -37,8 +38,8 @@ /// virtual registers to stack slots, rewriting the code. struct Spiller { virtual ~Spiller(); - virtual bool runOnMachineFunction(MachineFunction &MF, - VirtRegMap &VRM) = 0; + virtual bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs) = 0; }; /// createSpiller - Create an return a spiller object, as specified on the @@ -49,7 +50,8 @@ // Simple Spiller Implementation struct VISIBILITY_HIDDEN SimpleSpiller : public Spiller { - bool runOnMachineFunction(MachineFunction& mf, VirtRegMap &VRM); + bool runOnMachineFunction(MachineFunction& mf, VirtRegMap &VRM, + LiveIntervals* LIs); }; // ************************************************************************ // @@ -287,7 +289,8 @@ BitVector AllocatableRegs; DenseMap DistanceMap; public: - bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM); + bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LI); private: void TransferDeadness(MachineBasicBlock *MBB, unsigned CurDist, unsigned Reg, BitVector &RegKills, @@ -329,7 +332,7 @@ VirtRegMap &VRM); void RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM, - AvailableSpills &Spills, + LiveIntervals *LIs, AvailableSpills &Spills, BitVector &RegKills, std::vector &KillOps); }; } Added: llvm/trunk/test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll?rev=69743&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll (added) +++ llvm/trunk/test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll Tue Apr 21 17:46:52 2009 @@ -0,0 +1,25 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin10.0 -relocation-model=pic -disable-fp-elim -mattr=-sse41,-sse3,+sse2 | \ +; RUN: %prcontext {14} 2 | grep {(%ebp)} | count 1 +; rdar://6808032 + +define void @update(i8** %args_list) nounwind { +entry: + %cmp.i = icmp eq i32 0, 0 ; [#uses=1] + br i1 %cmp.i, label %if.then.i, label %test_cl.exit + +if.then.i: ; preds = %entry + %val = load <16 x i8> addrspace(1)* null ; <<16 x i8>> [#uses=8] + %tmp10.i = shufflevector <16 x i8> , <16 x i8> %val, <16 x i32> ; <<16 x i8>> [#uses=1] + %tmp17.i = shufflevector <16 x i8> %tmp10.i, <16 x i8> %val, <16 x i32> ; <<16 x i8>> [#uses=1] + %tmp24.i = shufflevector <16 x i8> %tmp17.i, <16 x i8> %val, <16 x i32> ; <<16 x i8>> [#uses=1] + %tmp31.i = shufflevector <16 x i8> %tmp24.i, <16 x i8> %val, <16 x i32> ; <<16 x i8>> [#uses=1] + %tmp38.i = shufflevector <16 x i8> %tmp31.i, <16 x i8> %val, <16 x i32> ; <<16 x i8>> [#uses=1] + %tmp45.i = shufflevector <16 x i8> %tmp38.i, <16 x i8> %val, <16 x i32> ; <<16 x i8>> [#uses=1] + %tmp52.i = shufflevector <16 x i8> %tmp45.i, <16 x i8> %val, <16 x i32> ; <<16 x i8>> [#uses=1] + %tmp59.i = shufflevector <16 x i8> %tmp52.i, <16 x i8> %val, <16 x i32> ; <<16 x i8>> [#uses=1] + store <16 x i8> %tmp59.i, <16 x i8> addrspace(1)* null + ret void + +test_cl.exit: ; preds = %entry + ret void +} From gohman at apple.com Tue Apr 21 18:15:49 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 21 Apr 2009 23:15:49 -0000 Subject: [llvm-commits] [llvm] r69749 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolution.h lib/Analysis/ScalarEvolution.cpp Message-ID: <200904212315.n3LNFnbn009155@zion.cs.uiuc.edu> Author: djg Date: Tue Apr 21 18:15:49 2009 New Revision: 69749 URL: http://llvm.org/viewvc/llvm-project?rev=69749&view=rev Log: De-pImpl-ify ScalarEvolution. The pImpl pattern doesn't provide much practical benefit in the case of ScalarEvolution, and it's otherwise a nuisance. Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h llvm/trunk/lib/Analysis/ScalarEvolution.cpp Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=69749&r1=69748&r2=69749&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Tue Apr 21 18:15:49 2009 @@ -32,6 +32,7 @@ class Type; class SCEVHandle; class ScalarEvolution; + class TargetData; /// SCEV - This class represent an analyzed expression in the program. These /// are reference counted opaque objects that the client is not allowed to @@ -118,6 +119,7 @@ /// marker. struct SCEVCouldNotCompute : public SCEV { SCEVCouldNotCompute(); + ~SCEVCouldNotCompute(); // None of these methods are valid for this object. virtual bool isLoopInvariant(const Loop *L) const; @@ -195,10 +197,110 @@ /// they must ask this class for services. /// class ScalarEvolution : public FunctionPass { - void *Impl; // ScalarEvolution uses the pimpl pattern + /// F - The function we are analyzing. + /// + Function *F; + + /// LI - The loop information for the function we are currently analyzing. + /// + LoopInfo *LI; + + /// TD - The target data information for the target we are targetting. + /// + TargetData *TD; + + /// UnknownValue - This SCEV is used to represent unknown trip counts and + /// things. + SCEVHandle UnknownValue; + + /// Scalars - This is a cache of the scalars we have analyzed so far. + /// + std::map Scalars; + + /// BackedgeTakenCounts - Cache the backedge-taken count of the loops for + /// this function as they are computed. + std::map BackedgeTakenCounts; + + /// ConstantEvolutionLoopExitValue - This map contains entries for all of + /// the PHI instructions that we attempt to compute constant evolutions for. + /// This allows us to avoid potentially expensive recomputation of these + /// properties. An instruction maps to null if we are unable to compute its + /// exit value. + std::map ConstantEvolutionLoopExitValue; + + /// createSCEV - We know that there is no SCEV for the specified value. + /// Analyze the expression. + SCEVHandle createSCEV(Value *V); + + /// createNodeForPHI - Provide the special handling we need to analyze PHI + /// SCEVs. + SCEVHandle createNodeForPHI(PHINode *PN); + + /// ReplaceSymbolicValueWithConcrete - This looks up the computed SCEV value + /// for the specified instruction and replaces any references to the + /// symbolic value SymName with the specified value. This is used during + /// PHI resolution. + void ReplaceSymbolicValueWithConcrete(Instruction *I, + const SCEVHandle &SymName, + const SCEVHandle &NewVal); + + /// ComputeBackedgeTakenCount - Compute the number of times the specified + /// loop will iterate. + SCEVHandle ComputeBackedgeTakenCount(const Loop *L); + + /// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition + /// of 'icmp op load X, cst', try to see if we can compute the trip count. + SCEVHandle + ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, + Constant *RHS, + const Loop *L, + ICmpInst::Predicate p); + + /// ComputeBackedgeTakenCountExhaustively - If the trip is known to execute + /// a constant number of times (the condition evolves only from constants), + /// try to evaluate a few iterations of the loop until we get the exit + /// condition gets a value of ExitWhen (true or false). If we cannot + /// evaluate the trip count of the loop, return UnknownValue. + SCEVHandle ComputeBackedgeTakenCountExhaustively(const Loop *L, Value *Cond, + bool ExitWhen); + + /// HowFarToZero - Return the number of times a backedge comparing the + /// specified value to zero will execute. If not computable, return + /// UnknownValue. + SCEVHandle HowFarToZero(SCEV *V, const Loop *L); + + /// HowFarToNonZero - Return the number of times a backedge checking the + /// specified value for nonzero will execute. If not computable, return + /// UnknownValue. + SCEVHandle HowFarToNonZero(SCEV *V, const Loop *L); + + /// HowManyLessThans - Return the number of times a backedge containing the + /// specified less-than comparison will execute. If not computable, return + /// UnknownValue. isSigned specifies whether the less-than is signed. + SCEVHandle HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L, + bool isSigned); + + /// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB + /// (which may not be an immediate predecessor) which has exactly one + /// successor from which BB is reachable, or null if no such block is + /// found. + BasicBlock* getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB); + + /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is + /// in the header of its containing loop, we know the loop executes a + /// constant number of times, and the PHI node is just a recurrence + /// involving constants, fold it. + Constant *getConstantEvolutionLoopExitValue(PHINode *PN, const APInt& BEs, + const Loop *L); + + /// getSCEVAtScope - Compute the value of the specified expression within + /// the indicated loop (which may be null to indicate in no loop). If the + /// expression cannot be evaluated, return UnknownValue itself. + SCEVHandle getSCEVAtScope(SCEV *S, const Loop *L); + public: static char ID; // Pass identification, replacement for typeid - ScalarEvolution() : FunctionPass(&ID), Impl(0) {} + ScalarEvolution(); /// isSCEVable - Test if values of the given type are analyzable within /// the SCEV framework. This primarily includes integer types, and it @@ -218,7 +320,7 @@ /// getSCEV - Return a SCEV expression handle for the full generality of the /// specified expression. - SCEVHandle getSCEV(Value *V) const; + SCEVHandle getSCEV(Value *V); SCEVHandle getConstant(ConstantInt *V); SCEVHandle getConstant(const APInt& Val); @@ -309,7 +411,7 @@ /// /// If this value is not computable at this scope, a SCEVCouldNotCompute /// object is returned. - SCEVHandle getSCEVAtScope(Value *V, const Loop *L) const; + SCEVHandle getSCEVAtScope(Value *V, const Loop *L); /// isLoopGuardedByCond - Test whether entry to the loop is protected by /// a conditional between LHS and RHS. @@ -327,11 +429,11 @@ /// loop-invariant backedge-taken count (see /// hasLoopInvariantBackedgeTakenCount). /// - SCEVHandle getBackedgeTakenCount(const Loop *L) const; + SCEVHandle getBackedgeTakenCount(const Loop *L); /// hasLoopInvariantBackedgeTakenCount - Return true if the specified loop /// has an analyzable loop-invariant backedge-taken count. - bool hasLoopInvariantBackedgeTakenCount(const Loop *L) const; + bool hasLoopInvariantBackedgeTakenCount(const Loop *L); /// forgetLoopBackedgeTakenCount - This method should be called by the /// client when it has changed a loop in a way that may effect @@ -342,7 +444,7 @@ /// deleteValueFromRecords - This method should be called by the /// client before it removes a Value from the program, to make sure /// that no dangling references are left around. - void deleteValueFromRecords(Value *V) const; + void deleteValueFromRecords(Value *V); virtual bool runOnFunction(Function &F); virtual void releaseMemory(); Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69749&r1=69748&r2=69749&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Tue Apr 21 18:15:49 2009 @@ -132,6 +132,7 @@ SCEVCouldNotCompute::SCEVCouldNotCompute() : SCEV(scCouldNotCompute) {} +SCEVCouldNotCompute::~SCEVCouldNotCompute() {} bool SCEVCouldNotCompute::isLoopInvariant(const Loop *L) const { assert(0 && "Attempt to use a SCEVCouldNotCompute object!"); @@ -1338,231 +1339,13 @@ } //===----------------------------------------------------------------------===// -// ScalarEvolutionsImpl Definition and Implementation -//===----------------------------------------------------------------------===// -// -/// ScalarEvolutionsImpl - This class implements the main driver for the scalar -/// evolution code. -/// -namespace { - struct VISIBILITY_HIDDEN ScalarEvolutionsImpl { - /// SE - A reference to the public ScalarEvolution object. - ScalarEvolution &SE; - - /// F - The function we are analyzing. - /// - Function &F; - - /// LI - The loop information for the function we are currently analyzing. - /// - LoopInfo &LI; - - /// TD - The target data information for the target we are targetting. - /// - TargetData *TD; - - /// UnknownValue - This SCEV is used to represent unknown trip counts and - /// things. - SCEVHandle UnknownValue; - - /// Scalars - This is a cache of the scalars we have analyzed so far. - /// - std::map Scalars; - - /// BackedgeTakenCounts - Cache the backedge-taken count of the loops for - /// this function as they are computed. - std::map BackedgeTakenCounts; - - /// ConstantEvolutionLoopExitValue - This map contains entries for all of - /// the PHI instructions that we attempt to compute constant evolutions for. - /// This allows us to avoid potentially expensive recomputation of these - /// properties. An instruction maps to null if we are unable to compute its - /// exit value. - std::map ConstantEvolutionLoopExitValue; - - public: - ScalarEvolutionsImpl(ScalarEvolution &se, Function &f, LoopInfo &li, - TargetData *td) - : SE(se), F(f), LI(li), TD(td), UnknownValue(new SCEVCouldNotCompute()) {} - - /// isSCEVable - Test if values of the given type are analyzable within - /// the SCEV framework. This primarily includes integer types, and it - /// can optionally include pointer types if the ScalarEvolution class - /// has access to target-specific information. - bool isSCEVable(const Type *Ty) const; - - /// getTypeSizeInBits - Return the size in bits of the specified type, - /// for which isSCEVable must return true. - uint64_t getTypeSizeInBits(const Type *Ty) const; - - /// getEffectiveSCEVType - Return a type with the same bitwidth as - /// the given type and which represents how SCEV will treat the given - /// type, for which isSCEVable must return true. For pointer types, - /// this is the pointer-sized integer type. - const Type *getEffectiveSCEVType(const Type *Ty) const; - - SCEVHandle getCouldNotCompute(); - - /// getIntegerSCEV - Given an integer or FP type, create a constant for the - /// specified signed integer value and return a SCEV for the constant. - SCEVHandle getIntegerSCEV(int Val, const Type *Ty); - - /// getNegativeSCEV - Return a SCEV corresponding to -V = -1*V - /// - SCEVHandle getNegativeSCEV(const SCEVHandle &V); - - /// getNotSCEV - Return a SCEV corresponding to ~V = -1-V - /// - SCEVHandle getNotSCEV(const SCEVHandle &V); - - /// getMinusSCEV - Return a SCEV corresponding to LHS - RHS. - /// - SCEVHandle getMinusSCEV(const SCEVHandle &LHS, const SCEVHandle &RHS); - - /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion - /// of the input value to the specified type. If the type must be extended, - /// it is zero extended. - SCEVHandle getTruncateOrZeroExtend(const SCEVHandle &V, const Type *Ty); - - /// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion - /// of the input value to the specified type. If the type must be extended, - /// it is sign extended. - SCEVHandle getTruncateOrSignExtend(const SCEVHandle &V, const Type *Ty); - - /// getSCEV - Return an existing SCEV if it exists, otherwise analyze the - /// expression and create a new one. - SCEVHandle getSCEV(Value *V); - - /// hasSCEV - Return true if the SCEV for this value has already been - /// computed. - bool hasSCEV(Value *V) const { - return Scalars.count(V); - } - - /// setSCEV - Insert the specified SCEV into the map of current SCEVs for - /// the specified value. - void setSCEV(Value *V, const SCEVHandle &H) { - bool isNew = Scalars.insert(std::make_pair(V, H)).second; - assert(isNew && "This entry already existed!"); - isNew = false; - } - - - /// getSCEVAtScope - Compute the value of the specified expression within - /// the indicated loop (which may be null to indicate in no loop). If the - /// expression cannot be evaluated, return UnknownValue itself. - SCEVHandle getSCEVAtScope(SCEV *V, const Loop *L); - - - /// isLoopGuardedByCond - Test whether entry to the loop is protected by - /// a conditional between LHS and RHS. - bool isLoopGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, - SCEV *LHS, SCEV *RHS); - - /// hasLoopInvariantBackedgeTakenCount - Return true if the specified loop - /// has an analyzable loop-invariant backedge-taken count. - bool hasLoopInvariantBackedgeTakenCount(const Loop *L); - - /// forgetLoopBackedgeTakenCount - This method should be called by the - /// client when it has changed a loop in a way that may effect - /// ScalarEvolution's ability to compute a trip count, or if the loop - /// is deleted. - void forgetLoopBackedgeTakenCount(const Loop *L); - - /// getBackedgeTakenCount - If the specified loop has a predictable - /// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute - /// object. The backedge-taken count is the number of times the loop header - /// will be branched to from within the loop. This is one less than the - /// trip count of the loop, since it doesn't count the first iteration, - /// when the header is branched to from outside the loop. - /// - /// Note that it is not valid to call this method on a loop without a - /// loop-invariant backedge-taken count (see - /// hasLoopInvariantBackedgeTakenCount). - /// - SCEVHandle getBackedgeTakenCount(const Loop *L); - - /// deleteValueFromRecords - This method should be called by the - /// client before it removes a value from the program, to make sure - /// that no dangling references are left around. - void deleteValueFromRecords(Value *V); - - private: - /// createSCEV - We know that there is no SCEV for the specified value. - /// Analyze the expression. - SCEVHandle createSCEV(Value *V); - - /// createNodeForPHI - Provide the special handling we need to analyze PHI - /// SCEVs. - SCEVHandle createNodeForPHI(PHINode *PN); - - /// ReplaceSymbolicValueWithConcrete - This looks up the computed SCEV value - /// for the specified instruction and replaces any references to the - /// symbolic value SymName with the specified value. This is used during - /// PHI resolution. - void ReplaceSymbolicValueWithConcrete(Instruction *I, - const SCEVHandle &SymName, - const SCEVHandle &NewVal); - - /// ComputeBackedgeTakenCount - Compute the number of times the specified - /// loop will iterate. - SCEVHandle ComputeBackedgeTakenCount(const Loop *L); - - /// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition - /// of 'icmp op load X, cst', try to see if we can compute the trip count. - SCEVHandle - ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, - Constant *RHS, - const Loop *L, - ICmpInst::Predicate p); - - /// ComputeBackedgeTakenCountExhaustively - If the trip is known to execute - /// a constant number of times (the condition evolves only from constants), - /// try to evaluate a few iterations of the loop until we get the exit - /// condition gets a value of ExitWhen (true or false). If we cannot - /// evaluate the trip count of the loop, return UnknownValue. - SCEVHandle ComputeBackedgeTakenCountExhaustively(const Loop *L, Value *Cond, - bool ExitWhen); - - /// HowFarToZero - Return the number of times a backedge comparing the - /// specified value to zero will execute. If not computable, return - /// UnknownValue. - SCEVHandle HowFarToZero(SCEV *V, const Loop *L); - - /// HowFarToNonZero - Return the number of times a backedge checking the - /// specified value for nonzero will execute. If not computable, return - /// UnknownValue. - SCEVHandle HowFarToNonZero(SCEV *V, const Loop *L); - - /// HowManyLessThans - Return the number of times a backedge containing the - /// specified less-than comparison will execute. If not computable, return - /// UnknownValue. isSigned specifies whether the less-than is signed. - SCEVHandle HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L, - bool isSigned); - - /// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB - /// (which may not be an immediate predecessor) which has exactly one - /// successor from which BB is reachable, or null if no such block is - /// found. - BasicBlock* getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB); - - /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is - /// in the header of its containing loop, we know the loop executes a - /// constant number of times, and the PHI node is just a recurrence - /// involving constants, fold it. - Constant *getConstantEvolutionLoopExitValue(PHINode *PN, const APInt& BEs, - const Loop *L); - }; -} - -//===----------------------------------------------------------------------===// // Basic SCEV Analysis and PHI Idiom Recognition Code // /// deleteValueFromRecords - This method should be called by the /// client before it removes an instruction from the program, to make sure /// that no dangling references are left around. -void ScalarEvolutionsImpl::deleteValueFromRecords(Value *V) { +void ScalarEvolution::deleteValueFromRecords(Value *V) { SmallVector Worklist; if (Scalars.erase(V)) { @@ -1591,7 +1374,7 @@ /// the SCEV framework. This primarily includes integer types, and it /// can optionally include pointer types if the ScalarEvolution class /// has access to target-specific information. -bool ScalarEvolutionsImpl::isSCEVable(const Type *Ty) const { +bool ScalarEvolution::isSCEVable(const Type *Ty) const { // Integers are always SCEVable. if (Ty->isInteger()) return true; @@ -1607,7 +1390,7 @@ /// getTypeSizeInBits - Return the size in bits of the specified type, /// for which isSCEVable must return true. -uint64_t ScalarEvolutionsImpl::getTypeSizeInBits(const Type *Ty) const { +uint64_t ScalarEvolution::getTypeSizeInBits(const Type *Ty) const { assert(isSCEVable(Ty) && "Type is not SCEVable!"); // If we have a TargetData, use it! @@ -1623,7 +1406,7 @@ /// the given type and which represents how SCEV will treat the given /// type, for which isSCEVable must return true. For pointer types, /// this is the pointer-sized integer type. -const Type *ScalarEvolutionsImpl::getEffectiveSCEVType(const Type *Ty) const { +const Type *ScalarEvolution::getEffectiveSCEVType(const Type *Ty) const { assert(isSCEVable(Ty) && "Type is not SCEVable!"); if (Ty->isInteger()) @@ -1633,13 +1416,13 @@ return TD->getIntPtrType(); } -SCEVHandle ScalarEvolutionsImpl::getCouldNotCompute() { +SCEVHandle ScalarEvolution::getCouldNotCompute() { return UnknownValue; } /// getSCEV - Return an existing SCEV if it exists, otherwise analyze the /// expression and create a new one. -SCEVHandle ScalarEvolutionsImpl::getSCEV(Value *V) { +SCEVHandle ScalarEvolution::getSCEV(Value *V) { assert(isSCEVable(V->getType()) && "Value is not SCEVable!"); std::map::iterator I = Scalars.find(V); @@ -1651,8 +1434,8 @@ /// getIntegerSCEV - Given an integer or FP type, create a constant for the /// specified signed integer value and return a SCEV for the constant. -SCEVHandle ScalarEvolutionsImpl::getIntegerSCEV(int Val, const Type *Ty) { - Ty = SE.getEffectiveSCEVType(Ty); +SCEVHandle ScalarEvolution::getIntegerSCEV(int Val, const Type *Ty) { + Ty = getEffectiveSCEVType(Ty); Constant *C; if (Val == 0) C = Constant::getNullValue(Ty); @@ -1661,44 +1444,44 @@ APFloat::IEEEdouble, Val)); else C = ConstantInt::get(Ty, Val); - return SE.getUnknown(C); + return getUnknown(C); } /// getNegativeSCEV - Return a SCEV corresponding to -V = -1*V /// -SCEVHandle ScalarEvolutionsImpl::getNegativeSCEV(const SCEVHandle &V) { +SCEVHandle ScalarEvolution::getNegativeSCEV(const SCEVHandle &V) { if (SCEVConstant *VC = dyn_cast(V)) - return SE.getUnknown(ConstantExpr::getNeg(VC->getValue())); + return getUnknown(ConstantExpr::getNeg(VC->getValue())); const Type *Ty = V->getType(); - Ty = SE.getEffectiveSCEVType(Ty); - return SE.getMulExpr(V, SE.getConstant(ConstantInt::getAllOnesValue(Ty))); + Ty = getEffectiveSCEVType(Ty); + return getMulExpr(V, getConstant(ConstantInt::getAllOnesValue(Ty))); } /// getNotSCEV - Return a SCEV corresponding to ~V = -1-V -SCEVHandle ScalarEvolutionsImpl::getNotSCEV(const SCEVHandle &V) { +SCEVHandle ScalarEvolution::getNotSCEV(const SCEVHandle &V) { if (SCEVConstant *VC = dyn_cast(V)) - return SE.getUnknown(ConstantExpr::getNot(VC->getValue())); + return getUnknown(ConstantExpr::getNot(VC->getValue())); const Type *Ty = V->getType(); - Ty = SE.getEffectiveSCEVType(Ty); - SCEVHandle AllOnes = SE.getConstant(ConstantInt::getAllOnesValue(Ty)); + Ty = getEffectiveSCEVType(Ty); + SCEVHandle AllOnes = getConstant(ConstantInt::getAllOnesValue(Ty)); return getMinusSCEV(AllOnes, V); } /// getMinusSCEV - Return a SCEV corresponding to LHS - RHS. /// -SCEVHandle ScalarEvolutionsImpl::getMinusSCEV(const SCEVHandle &LHS, +SCEVHandle ScalarEvolution::getMinusSCEV(const SCEVHandle &LHS, const SCEVHandle &RHS) { // X - Y --> X + -Y - return SE.getAddExpr(LHS, SE.getNegativeSCEV(RHS)); + return getAddExpr(LHS, getNegativeSCEV(RHS)); } /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion of the /// input value to the specified type. If the type must be extended, it is zero /// extended. SCEVHandle -ScalarEvolutionsImpl::getTruncateOrZeroExtend(const SCEVHandle &V, +ScalarEvolution::getTruncateOrZeroExtend(const SCEVHandle &V, const Type *Ty) { const Type *SrcTy = V->getType(); assert((SrcTy->isInteger() || (TD && isa(SrcTy))) && @@ -1707,15 +1490,15 @@ if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) return V; // No conversion if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty)) - return SE.getTruncateExpr(V, Ty); - return SE.getZeroExtendExpr(V, Ty); + return getTruncateExpr(V, Ty); + return getZeroExtendExpr(V, Ty); } /// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion of the /// input value to the specified type. If the type must be extended, it is sign /// extended. SCEVHandle -ScalarEvolutionsImpl::getTruncateOrSignExtend(const SCEVHandle &V, +ScalarEvolution::getTruncateOrSignExtend(const SCEVHandle &V, const Type *Ty) { const Type *SrcTy = V->getType(); assert((SrcTy->isInteger() || (TD && isa(SrcTy))) && @@ -1724,21 +1507,21 @@ if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) return V; // No conversion if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty)) - return SE.getTruncateExpr(V, Ty); - return SE.getSignExtendExpr(V, Ty); + return getTruncateExpr(V, Ty); + return getSignExtendExpr(V, Ty); } /// ReplaceSymbolicValueWithConcrete - This looks up the computed SCEV value for /// the specified instruction and replaces any references to the symbolic value /// SymName with the specified value. This is used during PHI resolution. -void ScalarEvolutionsImpl:: +void ScalarEvolution:: ReplaceSymbolicValueWithConcrete(Instruction *I, const SCEVHandle &SymName, const SCEVHandle &NewVal) { std::map::iterator SI = Scalars.find(I); if (SI == Scalars.end()) return; SCEVHandle NV = - SI->second->replaceSymbolicValuesWithConcrete(SymName, NewVal, SE); + SI->second->replaceSymbolicValuesWithConcrete(SymName, NewVal, *this); if (NV == SI->second) return; // No change. SI->second = NV; // Update the scalars map! @@ -1753,9 +1536,9 @@ /// createNodeForPHI - PHI nodes have two cases. Either the PHI node exists in /// a loop header, making it a potential recurrence, or it doesn't. /// -SCEVHandle ScalarEvolutionsImpl::createNodeForPHI(PHINode *PN) { +SCEVHandle ScalarEvolution::createNodeForPHI(PHINode *PN) { if (PN->getNumIncomingValues() == 2) // The loops have been canonicalized. - if (const Loop *L = LI.getLoopFor(PN->getParent())) + if (const Loop *L = LI->getLoopFor(PN->getParent())) if (L->getHeader() == PN->getParent()) { // If it lives in the loop header, it has two incoming values, one // from outside the loop, and one from inside. @@ -1763,7 +1546,7 @@ unsigned BackEdge = IncomingEdge^1; // While we are analyzing this PHI node, handle its value symbolically. - SCEVHandle SymbolicName = SE.getUnknown(PN); + SCEVHandle SymbolicName = getUnknown(PN); assert(Scalars.find(PN) == Scalars.end() && "PHI node already processed?"); Scalars.insert(std::make_pair(PN, SymbolicName)); @@ -1794,7 +1577,7 @@ for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i) if (i != FoundIndex) Ops.push_back(Add->getOperand(i)); - SCEVHandle Accum = SE.getAddExpr(Ops); + SCEVHandle Accum = getAddExpr(Ops); // This is not a valid addrec if the step amount is varying each // loop iteration, but is not itself an addrec in this loop. @@ -1802,7 +1585,7 @@ (isa(Accum) && cast(Accum)->getLoop() == L)) { SCEVHandle StartVal = getSCEV(PN->getIncomingValue(IncomingEdge)); - SCEVHandle PHISCEV = SE.getAddRecExpr(StartVal, Accum, L); + SCEVHandle PHISCEV = getAddRecExpr(StartVal, Accum, L); // Okay, for the entire analysis of this edge we assumed the PHI // to be symbolic. We now need to go back and update all of the @@ -1824,10 +1607,10 @@ // If StartVal = j.start - j.stride, we can use StartVal as the // initial step of the addrec evolution. - if (StartVal == SE.getMinusSCEV(AddRec->getOperand(0), + if (StartVal == getMinusSCEV(AddRec->getOperand(0), AddRec->getOperand(1))) { SCEVHandle PHISCEV = - SE.getAddRecExpr(StartVal, AddRec->getOperand(1), L); + getAddRecExpr(StartVal, AddRec->getOperand(1), L); // Okay, for the entire analysis of this edge we assumed the PHI // to be symbolic. We now need to go back and update all of the @@ -1844,7 +1627,7 @@ } // If it's not a loop phi, we can't handle it yet. - return SE.getUnknown(PN); + return getUnknown(PN); } /// GetMinTrailingZeros - Determine the minimum number of zero bits that S is @@ -1921,9 +1704,9 @@ /// createSCEV - We know that there is no SCEV for the specified value. /// Analyze the expression. /// -SCEVHandle ScalarEvolutionsImpl::createSCEV(Value *V) { +SCEVHandle ScalarEvolution::createSCEV(Value *V) { if (!isSCEVable(V->getType())) - return SE.getUnknown(V); + return getUnknown(V); unsigned Opcode = Instruction::UserOp1; if (Instruction *I = dyn_cast(V)) @@ -1931,22 +1714,22 @@ else if (ConstantExpr *CE = dyn_cast(V)) Opcode = CE->getOpcode(); else - return SE.getUnknown(V); + return getUnknown(V); User *U = cast(V); switch (Opcode) { case Instruction::Add: - return SE.getAddExpr(getSCEV(U->getOperand(0)), - getSCEV(U->getOperand(1))); + return getAddExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); case Instruction::Mul: - return SE.getMulExpr(getSCEV(U->getOperand(0)), - getSCEV(U->getOperand(1))); + return getMulExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); case Instruction::UDiv: - return SE.getUDivExpr(getSCEV(U->getOperand(0)), - getSCEV(U->getOperand(1))); + return getUDivExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); case Instruction::Sub: - return SE.getMinusSCEV(getSCEV(U->getOperand(0)), - getSCEV(U->getOperand(1))); + return getMinusSCEV(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); case Instruction::And: // For an expression like x&255 that merely masks off the high bits, // use zext(trunc(x)) as the SCEV expression. @@ -1955,9 +1738,9 @@ unsigned Ones = A.countTrailingOnes(); if (APIntOps::isMask(Ones, A)) return - SE.getZeroExtendExpr(SE.getTruncateExpr(getSCEV(U->getOperand(0)), - IntegerType::get(Ones)), - U->getType()); + getZeroExtendExpr(getTruncateExpr(getSCEV(U->getOperand(0)), + IntegerType::get(Ones)), + U->getType()); } break; case Instruction::Or: @@ -1970,9 +1753,9 @@ if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { SCEVHandle LHS = getSCEV(U->getOperand(0)); const APInt &CIVal = CI->getValue(); - if (GetMinTrailingZeros(LHS, SE) >= + if (GetMinTrailingZeros(LHS, *this) >= (CIVal.getBitWidth() - CIVal.countLeadingZeros())) - return SE.getAddExpr(LHS, getSCEV(U->getOperand(1))); + return getAddExpr(LHS, getSCEV(U->getOperand(1))); } break; case Instruction::Xor: @@ -1980,12 +1763,12 @@ // If the RHS of the xor is a signbit, then this is just an add. // Instcombine turns add of signbit into xor as a strength reduction step. if (CI->getValue().isSignBit()) - return SE.getAddExpr(getSCEV(U->getOperand(0)), - getSCEV(U->getOperand(1))); + return getAddExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); // If the RHS of xor is -1, then this is a not operation. else if (CI->isAllOnesValue()) - return SE.getNotSCEV(getSCEV(U->getOperand(0))); + return getNotSCEV(getSCEV(U->getOperand(0))); } break; @@ -1995,7 +1778,7 @@ uint32_t BitWidth = cast(V->getType())->getBitWidth(); Constant *X = ConstantInt::get( APInt(BitWidth, 1).shl(SA->getLimitedValue(BitWidth))); - return SE.getMulExpr(getSCEV(U->getOperand(0)), getSCEV(X)); + return getMulExpr(getSCEV(U->getOperand(0)), getSCEV(X)); } break; @@ -2005,7 +1788,7 @@ uint32_t BitWidth = cast(V->getType())->getBitWidth(); Constant *X = ConstantInt::get( APInt(BitWidth, 1).shl(SA->getLimitedValue(BitWidth))); - return SE.getUDivExpr(getSCEV(U->getOperand(0)), getSCEV(X)); + return getUDivExpr(getSCEV(U->getOperand(0)), getSCEV(X)); } break; @@ -2017,20 +1800,20 @@ L->getOperand(1) == U->getOperand(1)) { uint64_t Amt = getTypeSizeInBits(U->getType()) - CI->getZExtValue(); return - SE.getSignExtendExpr(SE.getTruncateExpr(getSCEV(L->getOperand(0)), + getSignExtendExpr(getTruncateExpr(getSCEV(L->getOperand(0)), IntegerType::get(Amt)), U->getType()); } break; case Instruction::Trunc: - return SE.getTruncateExpr(getSCEV(U->getOperand(0)), U->getType()); + return getTruncateExpr(getSCEV(U->getOperand(0)), U->getType()); case Instruction::ZExt: - return SE.getZeroExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + return getZeroExtendExpr(getSCEV(U->getOperand(0)), U->getType()); case Instruction::SExt: - return SE.getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + return getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType()); case Instruction::BitCast: // BitCasts are no-op casts so we just eliminate the cast. @@ -2052,7 +1835,7 @@ if (!TD) break; // Without TD we can't analyze pointers. const Type *IntPtrTy = TD->getIntPtrType(); Value *Base = U->getOperand(0); - SCEVHandle TotalOffset = SE.getIntegerSCEV(0, IntPtrTy); + SCEVHandle TotalOffset = getIntegerSCEV(0, IntPtrTy); gep_type_iterator GTI = gep_type_begin(U); for (GetElementPtrInst::op_iterator I = next(U->op_begin()), E = U->op_end(); @@ -2064,8 +1847,8 @@ const StructLayout &SL = *TD->getStructLayout(STy); unsigned FieldNo = cast(Index)->getZExtValue(); uint64_t Offset = SL.getElementOffset(FieldNo); - TotalOffset = SE.getAddExpr(TotalOffset, - SE.getIntegerSCEV(Offset, IntPtrTy)); + TotalOffset = getAddExpr(TotalOffset, + getIntegerSCEV(Offset, IntPtrTy)); } else { // For an array, add the element offset, explicitly scaled. SCEVHandle LocalOffset = getSCEV(Index); @@ -2074,13 +1857,13 @@ LocalOffset = getTruncateOrSignExtend(LocalOffset, IntPtrTy); LocalOffset = - SE.getMulExpr(LocalOffset, - SE.getIntegerSCEV(TD->getTypePaddedSize(*GTI), - IntPtrTy)); - TotalOffset = SE.getAddExpr(TotalOffset, LocalOffset); + getMulExpr(LocalOffset, + getIntegerSCEV(TD->getTypePaddedSize(*GTI), + IntPtrTy)); + TotalOffset = getAddExpr(TotalOffset, LocalOffset); } } - return SE.getAddExpr(getSCEV(Base), TotalOffset); + return getAddExpr(getSCEV(Base), TotalOffset); } case Instruction::PHI: @@ -2100,12 +1883,12 @@ case ICmpInst::ICMP_SGT: case ICmpInst::ICMP_SGE: if (LHS == U->getOperand(1) && RHS == U->getOperand(2)) - return SE.getSMaxExpr(getSCEV(LHS), getSCEV(RHS)); + return getSMaxExpr(getSCEV(LHS), getSCEV(RHS)); else if (LHS == U->getOperand(2) && RHS == U->getOperand(1)) // ~smax(~x, ~y) == smin(x, y). - return SE.getNotSCEV(SE.getSMaxExpr( - SE.getNotSCEV(getSCEV(LHS)), - SE.getNotSCEV(getSCEV(RHS)))); + return getNotSCEV(getSMaxExpr( + getNotSCEV(getSCEV(LHS)), + getNotSCEV(getSCEV(RHS)))); break; case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_ULE: @@ -2114,11 +1897,11 @@ case ICmpInst::ICMP_UGT: case ICmpInst::ICMP_UGE: if (LHS == U->getOperand(1) && RHS == U->getOperand(2)) - return SE.getUMaxExpr(getSCEV(LHS), getSCEV(RHS)); + return getUMaxExpr(getSCEV(LHS), getSCEV(RHS)); else if (LHS == U->getOperand(2) && RHS == U->getOperand(1)) // ~umax(~x, ~y) == umin(x, y) - return SE.getNotSCEV(SE.getUMaxExpr(SE.getNotSCEV(getSCEV(LHS)), - SE.getNotSCEV(getSCEV(RHS)))); + return getNotSCEV(getUMaxExpr(getNotSCEV(getSCEV(LHS)), + getNotSCEV(getSCEV(RHS)))); break; default: break; @@ -2129,7 +1912,7 @@ break; } - return SE.getUnknown(V); + return getUnknown(V); } @@ -2149,7 +1932,7 @@ /// loop-invariant backedge-taken count (see /// hasLoopInvariantBackedgeTakenCount). /// -SCEVHandle ScalarEvolutionsImpl::getBackedgeTakenCount(const Loop *L) { +SCEVHandle ScalarEvolution::getBackedgeTakenCount(const Loop *L) { std::map::iterator I = BackedgeTakenCounts.find(L); if (I == BackedgeTakenCounts.end()) { SCEVHandle ItCount = ComputeBackedgeTakenCount(L); @@ -2170,13 +1953,13 @@ /// client when it has changed a loop in a way that may effect /// ScalarEvolution's ability to compute a trip count, or if the loop /// is deleted. -void ScalarEvolutionsImpl::forgetLoopBackedgeTakenCount(const Loop *L) { +void ScalarEvolution::forgetLoopBackedgeTakenCount(const Loop *L) { BackedgeTakenCounts.erase(L); } /// ComputeBackedgeTakenCount - Compute the number of times the backedge /// of the specified loop will execute. -SCEVHandle ScalarEvolutionsImpl::ComputeBackedgeTakenCount(const Loop *L) { +SCEVHandle ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) { // If the loop has a non-one exit block count, we can't analyze it. SmallVector ExitBlocks; L->getExitBlocks(ExitBlocks); @@ -2278,7 +2061,7 @@ ConstantRange CompRange( ICmpInst::makeConstantRange(Cond, CompVal->getValue())); - SCEVHandle Ret = AddRec->getNumIterationsInRange(CompRange, SE); + SCEVHandle Ret = AddRec->getNumIterationsInRange(CompRange, *this); if (!isa(Ret)) return Ret; } } @@ -2286,13 +2069,13 @@ switch (Cond) { case ICmpInst::ICMP_NE: { // while (X != Y) // Convert to: while (X-Y != 0) - SCEVHandle TC = HowFarToZero(SE.getMinusSCEV(LHS, RHS), L); + SCEVHandle TC = HowFarToZero(getMinusSCEV(LHS, RHS), L); if (!isa(TC)) return TC; break; } case ICmpInst::ICMP_EQ: { // Convert to: while (X-Y == 0) // while (X == Y) - SCEVHandle TC = HowFarToNonZero(SE.getMinusSCEV(LHS, RHS), L); + SCEVHandle TC = HowFarToNonZero(getMinusSCEV(LHS, RHS), L); if (!isa(TC)) return TC; break; } @@ -2302,8 +2085,8 @@ break; } case ICmpInst::ICMP_SGT: { - SCEVHandle TC = HowManyLessThans(SE.getNotSCEV(LHS), - SE.getNotSCEV(RHS), L, true); + SCEVHandle TC = HowManyLessThans(getNotSCEV(LHS), + getNotSCEV(RHS), L, true); if (!isa(TC)) return TC; break; } @@ -2313,8 +2096,8 @@ break; } case ICmpInst::ICMP_UGT: { - SCEVHandle TC = HowManyLessThans(SE.getNotSCEV(LHS), - SE.getNotSCEV(RHS), L, false); + SCEVHandle TC = HowManyLessThans(getNotSCEV(LHS), + getNotSCEV(RHS), L, false); if (!isa(TC)) return TC; break; } @@ -2381,7 +2164,7 @@ /// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition of /// 'icmp op load X, cst', try to see if we can compute the backedge /// execution count. -SCEVHandle ScalarEvolutionsImpl:: +SCEVHandle ScalarEvolution:: ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, Constant *RHS, const Loop *L, ICmpInst::Predicate predicate) { @@ -2431,7 +2214,7 @@ for (unsigned IterationNum = 0; IterationNum != MaxSteps; ++IterationNum) { ConstantInt *ItCst = ConstantInt::get(IdxExpr->getType(), IterationNum); - ConstantInt *Val = EvaluateConstantChrecAtConstant(IdxExpr, ItCst, SE); + ConstantInt *Val = EvaluateConstantChrecAtConstant(IdxExpr, ItCst, *this); // Form the GEP offset. Indexes[VarIdxNum] = Val; @@ -2449,7 +2232,7 @@ << "***\n"; #endif ++NumArrayLenItCounts; - return SE.getConstant(ItCst); // Found terminating iteration! + return getConstant(ItCst); // Found terminating iteration! } } return UnknownValue; @@ -2541,7 +2324,7 @@ /// in the header of its containing loop, we know the loop executes a /// constant number of times, and the PHI node is just a recurrence /// involving constants, fold it. -Constant *ScalarEvolutionsImpl:: +Constant *ScalarEvolution:: getConstantEvolutionLoopExitValue(PHINode *PN, const APInt& BEs, const Loop *L){ std::map::iterator I = ConstantEvolutionLoopExitValue.find(PN); @@ -2592,7 +2375,7 @@ /// try to evaluate a few iterations of the loop until we get the exit /// condition gets a value of ExitWhen (true or false). If we cannot /// evaluate the trip count of the loop, return UnknownValue. -SCEVHandle ScalarEvolutionsImpl:: +SCEVHandle ScalarEvolution:: ComputeBackedgeTakenCountExhaustively(const Loop *L, Value *Cond, bool ExitWhen) { PHINode *PN = getConstantEvolvingPHI(Cond, L); if (PN == 0) return UnknownValue; @@ -2625,7 +2408,7 @@ if (CondVal->getValue() == uint64_t(ExitWhen)) { ConstantEvolutionLoopExitValue[PN] = PHIVal; ++NumBruteForceTripCountsComputed; - return SE.getConstant(ConstantInt::get(Type::Int32Ty, IterationNum)); + return getConstant(ConstantInt::get(Type::Int32Ty, IterationNum)); } // Compute the value of the PHI node for the next iteration. @@ -2642,7 +2425,7 @@ /// getSCEVAtScope - Compute the value of the specified expression within the /// indicated loop (which may be null to indicate in no loop). If the /// expression cannot be evaluated, return UnknownValue. -SCEVHandle ScalarEvolutionsImpl::getSCEVAtScope(SCEV *V, const Loop *L) { +SCEVHandle ScalarEvolution::getSCEVAtScope(SCEV *V, const Loop *L) { // FIXME: this should be turned into a virtual method on SCEV! if (isa(V)) return V; @@ -2651,7 +2434,7 @@ // exit value from the loop without using SCEVs. if (SCEVUnknown *SU = dyn_cast(V)) { if (Instruction *I = dyn_cast(SU->getValue())) { - const Loop *LI = this->LI[I->getParent()]; + const Loop *LI = (*this->LI)[I->getParent()]; if (LI && LI->getParentLoop() == L) // Looking for loop exit value. if (PHINode *PN = dyn_cast(I)) if (PN->getParent() == LI->getHeader()) { @@ -2668,7 +2451,7 @@ Constant *RV = getConstantEvolutionLoopExitValue(PN, BTCC->getValue()->getValue(), LI); - if (RV) return SE.getUnknown(RV); + if (RV) return getUnknown(RV); } } @@ -2716,7 +2499,7 @@ else C = ConstantFoldInstOperands(I->getOpcode(), I->getType(), &Operands[0], Operands.size()); - return SE.getUnknown(C); + return getUnknown(C); } } @@ -2742,13 +2525,13 @@ NewOps.push_back(OpAtScope); } if (isa(Comm)) - return SE.getAddExpr(NewOps); + return getAddExpr(NewOps); if (isa(Comm)) - return SE.getMulExpr(NewOps); + return getMulExpr(NewOps); if (isa(Comm)) - return SE.getSMaxExpr(NewOps); + return getSMaxExpr(NewOps); if (isa(Comm)) - return SE.getUMaxExpr(NewOps); + return getUMaxExpr(NewOps); assert(0 && "Unknown commutative SCEV type!"); } } @@ -2763,7 +2546,7 @@ if (RHS == UnknownValue) return RHS; if (LHS == Div->getLHS() && RHS == Div->getRHS()) return Div; // must be loop invariant - return SE.getUDivExpr(LHS, RHS); + return getUDivExpr(LHS, RHS); } // If this is a loop recurrence for a loop that does not contain L, then we @@ -2776,7 +2559,7 @@ if (BackedgeTakenCount == UnknownValue) return UnknownValue; // Then, evaluate the AddRec. - return AddRec->evaluateAtIteration(BackedgeTakenCount, SE); + return AddRec->evaluateAtIteration(BackedgeTakenCount, *this); } return UnknownValue; } @@ -2785,6 +2568,20 @@ return UnknownValue; } +/// getSCEVAtScope - Return a SCEV expression handle for the specified value +/// at the specified scope in the program. The L value specifies a loop +/// nest to evaluate the expression at, where null is the top-level or a +/// specified loop is immediately inside of the loop. +/// +/// This method can be used to compute the exit value for a variable defined +/// in a loop by querying what the value will hold in the parent loop. +/// +/// If this value is not computable at this scope, a SCEVCouldNotCompute +/// object is returned. +SCEVHandle ScalarEvolution::getSCEVAtScope(Value *V, const Loop *L) { + return getSCEVAtScope(getSCEV(V), L); +} + /// SolveLinEquationWithOverflow - Finds the minimum unsigned root of the /// following equation: /// @@ -2896,7 +2693,7 @@ /// HowFarToZero - Return the number of times a backedge comparing the specified /// value to zero will execute. If not computable, return UnknownValue -SCEVHandle ScalarEvolutionsImpl::HowFarToZero(SCEV *V, const Loop *L) { +SCEVHandle ScalarEvolution::HowFarToZero(SCEV *V, const Loop *L) { // If the value is a constant if (SCEVConstant *C = dyn_cast(V)) { // If the value is already zero, the branch will execute zero times. @@ -2931,19 +2728,21 @@ // First, handle unitary steps. if (StepC->getValue()->equalsInt(1)) // 1*N = -Start (mod 2^BW), so: - return SE.getNegativeSCEV(Start); // N = -Start (as unsigned) + return getNegativeSCEV(Start); // N = -Start (as unsigned) if (StepC->getValue()->isAllOnesValue()) // -1*N = -Start (mod 2^BW), so: return Start; // N = Start (as unsigned) // Then, try to solve the above equation provided that Start is constant. if (SCEVConstant *StartC = dyn_cast(Start)) return SolveLinEquationWithOverflow(StepC->getValue()->getValue(), - -StartC->getValue()->getValue(),SE); + -StartC->getValue()->getValue(), + *this); } } else if (AddRec->isQuadratic() && AddRec->getType()->isInteger()) { // If this is a quadratic (3-term) AddRec {L,+,M,+,N}, find the roots of // the quadratic equation to solve it. - std::pair Roots = SolveQuadraticEquation(AddRec, SE); + std::pair Roots = SolveQuadraticEquation(AddRec, + *this); SCEVConstant *R1 = dyn_cast(Roots.first); SCEVConstant *R2 = dyn_cast(Roots.second); if (R1) { @@ -2961,7 +2760,7 @@ // We can only use this value if the chrec ends up with an exact zero // value at this index. When solving for "X*X != 5", for example, we // should not accept a root of 2. - SCEVHandle Val = AddRec->evaluateAtIteration(R1, SE); + SCEVHandle Val = AddRec->evaluateAtIteration(R1, *this); if (Val->isZero()) return R1; // We found a quadratic root! } @@ -2974,7 +2773,7 @@ /// HowFarToNonZero - Return the number of times a backedge checking the /// specified value for nonzero will execute. If not computable, return /// UnknownValue -SCEVHandle ScalarEvolutionsImpl::HowFarToNonZero(SCEV *V, const Loop *L) { +SCEVHandle ScalarEvolution::HowFarToNonZero(SCEV *V, const Loop *L) { // Loops that look like: while (X == 0) are very strange indeed. We don't // handle them yet except for the trivial case. This could be expanded in the // future as needed. @@ -2983,7 +2782,7 @@ // already. If so, the backedge will execute zero times. if (SCEVConstant *C = dyn_cast(V)) { if (!C->getValue()->isNullValue()) - return SE.getIntegerSCEV(0, C->getType()); + return getIntegerSCEV(0, C->getType()); return UnknownValue; // Otherwise it will loop infinitely. } @@ -2998,7 +2797,7 @@ /// found. /// BasicBlock * -ScalarEvolutionsImpl::getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB) { +ScalarEvolution::getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB) { // If the block has a unique predecessor, the predecessor must have // no other successors from which BB is reachable. if (BasicBlock *Pred = BB->getSinglePredecessor()) @@ -3008,7 +2807,7 @@ // If the loop has a preheader, it must be a block that has exactly // one successor that can reach BB. This is slightly more strict // than necessary, but works if critical edges are split. - if (Loop *L = LI.getLoopFor(BB)) + if (Loop *L = LI->getLoopFor(BB)) return L->getLoopPreheader(); return 0; @@ -3016,7 +2815,7 @@ /// isLoopGuardedByCond - Test whether entry to the loop is protected by /// a conditional between LHS and RHS. -bool ScalarEvolutionsImpl::isLoopGuardedByCond(const Loop *L, +bool ScalarEvolution::isLoopGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, SCEV *LHS, SCEV *RHS) { BasicBlock *Preheader = L->getLoopPreheader(); @@ -3110,8 +2909,8 @@ SCEVHandle PreCondLHSSCEV = getSCEV(PreCondLHS); SCEVHandle PreCondRHSSCEV = getSCEV(PreCondRHS); if ((LHS == PreCondLHSSCEV && RHS == PreCondRHSSCEV) || - (LHS == SE.getNotSCEV(PreCondRHSSCEV) && - RHS == SE.getNotSCEV(PreCondLHSSCEV))) + (LHS == getNotSCEV(PreCondRHSSCEV) && + RHS == getNotSCEV(PreCondLHSSCEV))) return true; } @@ -3121,7 +2920,7 @@ /// HowManyLessThans - Return the number of times a backedge containing the /// specified less-than comparison will execute. If not computable, return /// UnknownValue. -SCEVHandle ScalarEvolutionsImpl:: +SCEVHandle ScalarEvolution:: HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L, bool isSigned) { // Only handle: "ADDREC < LoopInvariant". if (!RHS->isLoopInvariant(L)) return UnknownValue; @@ -3132,7 +2931,7 @@ if (AddRec->isAffine()) { // FORNOW: We only support unit strides. - SCEVHandle One = SE.getIntegerSCEV(1, RHS->getType()); + SCEVHandle One = getIntegerSCEV(1, RHS->getType()); if (AddRec->getOperand(1) != One) return UnknownValue; @@ -3146,19 +2945,19 @@ if (isLoopGuardedByCond(L, isSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT, - SE.getMinusSCEV(AddRec->getOperand(0), One), RHS)) { + getMinusSCEV(AddRec->getOperand(0), One), RHS)) { // Since we know that the condition is true in order to enter the loop, // we know that it will run exactly m-n times. - return SE.getMinusSCEV(RHS, Start); + return getMinusSCEV(RHS, Start); } else { // Then, we get the value of the LHS in the first iteration in which the // above condition doesn't hold. This equals to max(m,n). - SCEVHandle End = isSigned ? SE.getSMaxExpr(RHS, Start) - : SE.getUMaxExpr(RHS, Start); + SCEVHandle End = isSigned ? getSMaxExpr(RHS, Start) + : getUMaxExpr(RHS, Start); // Finally, we subtract these two values to get the number of times the // backedge is executed: max(m,n)-n. - return SE.getMinusSCEV(End, Start); + return getMinusSCEV(End, Start); } } @@ -3291,16 +3090,21 @@ // ScalarEvolution Class Implementation //===----------------------------------------------------------------------===// +ScalarEvolution::ScalarEvolution() + : FunctionPass(&ID), UnknownValue(new SCEVCouldNotCompute()) { +} + bool ScalarEvolution::runOnFunction(Function &F) { - Impl = new ScalarEvolutionsImpl(*this, F, - getAnalysis(), - getAnalysisIfAvailable()); + this->F = &F; + LI = &getAnalysis(); + TD = getAnalysisIfAvailable(); return false; } void ScalarEvolution::releaseMemory() { - delete (ScalarEvolutionsImpl*)Impl; - Impl = 0; + Scalars.clear(); + BackedgeTakenCounts.clear(); + ConstantEvolutionLoopExitValue.clear(); } void ScalarEvolution::getAnalysisUsage(AnalysisUsage &AU) const { @@ -3308,107 +3112,11 @@ AU.addRequiredTransitive(); } -bool ScalarEvolution::isSCEVable(const Type *Ty) const { - return ((ScalarEvolutionsImpl*)Impl)->isSCEVable(Ty); -} - -uint64_t ScalarEvolution::getTypeSizeInBits(const Type *Ty) const { - return ((ScalarEvolutionsImpl*)Impl)->getTypeSizeInBits(Ty); -} - -const Type *ScalarEvolution::getEffectiveSCEVType(const Type *Ty) const { - return ((ScalarEvolutionsImpl*)Impl)->getEffectiveSCEVType(Ty); -} - -SCEVHandle ScalarEvolution::getCouldNotCompute() { - return ((ScalarEvolutionsImpl*)Impl)->getCouldNotCompute(); -} - -SCEVHandle ScalarEvolution::getIntegerSCEV(int Val, const Type *Ty) { - return ((ScalarEvolutionsImpl*)Impl)->getIntegerSCEV(Val, Ty); -} - -SCEVHandle ScalarEvolution::getSCEV(Value *V) const { - return ((ScalarEvolutionsImpl*)Impl)->getSCEV(V); -} - -/// hasSCEV - Return true if the SCEV for this value has already been -/// computed. -bool ScalarEvolution::hasSCEV(Value *V) const { - return ((ScalarEvolutionsImpl*)Impl)->hasSCEV(V); -} - - -/// setSCEV - Insert the specified SCEV into the map of current SCEVs for -/// the specified value. -void ScalarEvolution::setSCEV(Value *V, const SCEVHandle &H) { - ((ScalarEvolutionsImpl*)Impl)->setSCEV(V, H); -} - -/// getNegativeSCEV - Return a SCEV corresponding to -V = -1*V -/// -SCEVHandle ScalarEvolution::getNegativeSCEV(const SCEVHandle &V) { - return ((ScalarEvolutionsImpl*)Impl)->getNegativeSCEV(V); -} - -/// getNotSCEV - Return a SCEV corresponding to ~V = -1-V -/// -SCEVHandle ScalarEvolution::getNotSCEV(const SCEVHandle &V) { - return ((ScalarEvolutionsImpl*)Impl)->getNotSCEV(V); -} - -/// getMinusSCEV - Return a SCEV corresponding to LHS - RHS. -/// -SCEVHandle ScalarEvolution::getMinusSCEV(const SCEVHandle &LHS, - const SCEVHandle &RHS) { - return ((ScalarEvolutionsImpl*)Impl)->getMinusSCEV(LHS, RHS); -} - -/// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion -/// of the input value to the specified type. If the type must be -/// extended, it is zero extended. -SCEVHandle ScalarEvolution::getTruncateOrZeroExtend(const SCEVHandle &V, - const Type *Ty) { - return ((ScalarEvolutionsImpl*)Impl)->getTruncateOrZeroExtend(V, Ty); -} - -/// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion -/// of the input value to the specified type. If the type must be -/// extended, it is sign extended. -SCEVHandle ScalarEvolution::getTruncateOrSignExtend(const SCEVHandle &V, - const Type *Ty) { - return ((ScalarEvolutionsImpl*)Impl)->getTruncateOrSignExtend(V, Ty); -} - - -bool ScalarEvolution::isLoopGuardedByCond(const Loop *L, - ICmpInst::Predicate Pred, - SCEV *LHS, SCEV *RHS) { - return ((ScalarEvolutionsImpl*)Impl)->isLoopGuardedByCond(L, Pred, - LHS, RHS); -} - -SCEVHandle ScalarEvolution::getBackedgeTakenCount(const Loop *L) const { - return ((ScalarEvolutionsImpl*)Impl)->getBackedgeTakenCount(L); -} - -bool ScalarEvolution::hasLoopInvariantBackedgeTakenCount(const Loop *L) const { +bool ScalarEvolution::hasLoopInvariantBackedgeTakenCount(const Loop *L) { return !isa(getBackedgeTakenCount(L)); } -void ScalarEvolution::forgetLoopBackedgeTakenCount(const Loop *L) { - return ((ScalarEvolutionsImpl*)Impl)->forgetLoopBackedgeTakenCount(L); -} - -SCEVHandle ScalarEvolution::getSCEVAtScope(Value *V, const Loop *L) const { - return ((ScalarEvolutionsImpl*)Impl)->getSCEVAtScope(getSCEV(V), L); -} - -void ScalarEvolution::deleteValueFromRecords(Value *V) const { - return ((ScalarEvolutionsImpl*)Impl)->deleteValueFromRecords(V); -} - -static void PrintLoopInfo(raw_ostream &OS, const ScalarEvolution *SE, +static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE, const Loop *L) { // Print all inner loops first for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) @@ -3431,21 +3139,26 @@ } void ScalarEvolution::print(raw_ostream &OS, const Module* ) const { - Function &F = ((ScalarEvolutionsImpl*)Impl)->F; - LoopInfo &LI = ((ScalarEvolutionsImpl*)Impl)->LI; + // ScalarEvolution's implementaiton of the print method is to print + // out SCEV values of all instructions that are interesting. Doing + // this potentially causes it to create new SCEV objects though, + // which technically conflicts with the const qualifier. This isn't + // observable from outside the class though (the hasSCEV function + // notwithstanding), so casting away the const isn't dangerous. + ScalarEvolution &SE = *const_cast(this); - OS << "Classifying expressions for: " << F.getName() << "\n"; + OS << "Classifying expressions for: " << F->getName() << "\n"; for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) if (I->getType()->isInteger()) { OS << *I; OS << " --> "; - SCEVHandle SV = getSCEV(&*I); + SCEVHandle SV = SE.getSCEV(&*I); SV->print(OS); OS << "\t\t"; - if (const Loop *L = LI.getLoopFor((*I).getParent())) { + if (const Loop *L = LI->getLoopFor((*I).getParent())) { OS << "Exits: "; - SCEVHandle ExitValue = getSCEVAtScope(&*I, L->getParentLoop()); + SCEVHandle ExitValue = SE.getSCEVAtScope(&*I, L->getParentLoop()); if (isa(ExitValue)) { OS << "<>"; } else { @@ -3457,9 +3170,9 @@ OS << "\n"; } - OS << "Determining loop execution counts for: " << F.getName() << "\n"; - for (LoopInfo::iterator I = LI.begin(), E = LI.end(); I != E; ++I) - PrintLoopInfo(OS, this, *I); + OS << "Determining loop execution counts for: " << F->getName() << "\n"; + for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I) + PrintLoopInfo(OS, &SE, *I); } void ScalarEvolution::print(std::ostream &o, const Module *M) const { From sabre at nondot.org Tue Apr 21 18:37:18 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 21 Apr 2009 23:37:18 -0000 Subject: [llvm-commits] [llvm] r69752 - /llvm/trunk/lib/Transforms/Utils/InlineCost.cpp Message-ID: <200904212337.n3LNbId7009921@zion.cs.uiuc.edu> Author: lattner Date: Tue Apr 21 18:37:18 2009 New Revision: 69752 URL: http://llvm.org/viewvc/llvm-project?rev=69752&view=rev Log: use predicate instead of hand-rolled loop Modified: llvm/trunk/lib/Transforms/Utils/InlineCost.cpp Modified: llvm/trunk/lib/Transforms/Utils/InlineCost.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineCost.cpp?rev=69752&r1=69751&r2=69752&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/InlineCost.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/InlineCost.cpp Tue Apr 21 18:37:18 2009 @@ -76,10 +76,8 @@ Reduction += 10; else if (GetElementPtrInst *GEP = dyn_cast(I)) { // If the GEP has variable indices, we won't be able to do much with it. - for (Instruction::op_iterator I = GEP->op_begin()+1, E = GEP->op_end(); - I != E; ++I) - if (!isa(*I)) return 0; - Reduction += CountCodeReductionForAlloca(GEP)+15; + if (!GEP->hasAllConstantIndices()) + Reduction += CountCodeReductionForAlloca(GEP)+15; } else { // If there is some other strange instruction, we're not going to be able // to do much if we inline this. @@ -143,13 +141,8 @@ dyn_cast(II)) { // If a GEP has all constant indices, it will probably be folded with // a load/store. - bool AllConstant = true; - for (unsigned i = 1, e = GEPI->getNumOperands(); i != e; ++i) - if (!isa(GEPI->getOperand(i))) { - AllConstant = false; - break; - } - if (AllConstant) continue; + if (GEPI->hasAllConstantIndices()) + continue; } ++NumInsts; From kremenek at apple.com Tue Apr 21 21:59:23 2009 From: kremenek at apple.com (Ted Kremenek) Date: Wed, 22 Apr 2009 02:59:23 -0000 Subject: [llvm-commits] [llvm] r69768 - /llvm/tags/checker/checker-0.187/ Message-ID: <200904220259.n3M2xNaq016889@zion.cs.uiuc.edu> Author: kremenek Date: Tue Apr 21 21:59:23 2009 New Revision: 69768 URL: http://llvm.org/viewvc/llvm-project?rev=69768&view=rev Log: Tagging checker-0.187. Added: llvm/tags/checker/checker-0.187/ - copied from r69767, llvm/trunk/ From resistor at mac.com Wed Apr 22 02:16:55 2009 From: resistor at mac.com (Owen Anderson) Date: Wed, 22 Apr 2009 07:16:55 -0000 Subject: [llvm-commits] [llvm] r69785 - /llvm/trunk/include/llvm/ADT/SmallVector.h Message-ID: <200904220716.n3M7Gtnk025567@zion.cs.uiuc.edu> Author: resistor Date: Wed Apr 22 02:16:54 2009 New Revision: 69785 URL: http://llvm.org/viewvc/llvm-project?rev=69785&view=rev Log: Fix for PR3946, in which SmallVector could behave strangely in corner cases. Patch by Peter Johnson. 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=69785&r1=69784&r2=69785&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Wed Apr 22 02:16:54 2009 @@ -302,7 +302,7 @@ append(End-NumToInsert, End); // Copy the existing elements that get replaced. - std::copy(I, OldEnd-NumToInsert, I+NumToInsert); + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); std::fill_n(I, NumToInsert, Elt); return I; @@ -351,7 +351,7 @@ append(End-NumToInsert, End); // Copy the existing elements that get replaced. - std::copy(I, OldEnd-NumToInsert, I+NumToInsert); + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); std::copy(From, To, I); return I; From resistor at mac.com Wed Apr 22 03:09:15 2009 From: resistor at mac.com (Owen Anderson) Date: Wed, 22 Apr 2009 08:09:15 -0000 Subject: [llvm-commits] [llvm] r69788 - /llvm/trunk/lib/Transforms/Utils/LCSSA.cpp Message-ID: <200904220809.n3M89Gip031997@zion.cs.uiuc.edu> Author: resistor Date: Wed Apr 22 03:09:13 2009 New Revision: 69788 URL: http://llvm.org/viewvc/llvm-project?rev=69788&view=rev Log: Use PredIteratorCache in LCSSA, which gives a 37% overall speedup on the testcase from PR3549. More improvements to come. Modified: llvm/trunk/lib/Transforms/Utils/LCSSA.cpp Modified: llvm/trunk/lib/Transforms/Utils/LCSSA.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LCSSA.cpp?rev=69788&r1=69787&r2=69788&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/LCSSA.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/LCSSA.cpp Wed Apr 22 03:09:13 2009 @@ -40,6 +40,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/PredIteratorCache.h" #include #include using namespace llvm; @@ -55,6 +56,7 @@ LoopInfo *LI; DominatorTree *DT; std::vector LoopBlocks; + PredIteratorCache PredCache; virtual bool runOnLoop(Loop *L, LPPassManager &LPM); @@ -104,6 +106,7 @@ /// runOnFunction - Process all loops in the function, inner-most out. bool LCSSA::runOnLoop(Loop *L, LPPassManager &LPM) { + PredCache.clear(); LI = &LPM.getAnalysis(); DT = &getAnalysis(); @@ -163,7 +166,7 @@ Phi = PN; // Add inputs from inside the loop for this PHI. - for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + for (BasicBlock** PI = PredCache.GetPreds(BB); *PI; ++PI) PN->addIncoming(Instr, *PI); } } @@ -264,7 +267,7 @@ Phis.insert(std::make_pair(BB, PN)); // Fill in the incoming values for the block. - for (pred_iterator PI = pred_begin(BBN), E = pred_end(BBN); PI != E; ++PI) + for (BasicBlock** PI = PredCache.GetPreds(BBN); *PI; ++PI) PN->addIncoming(GetValueForBlock(DT->getNode(*PI), OrigInst, Phis), *PI); return PN; } From resistor at mac.com Wed Apr 22 03:46:52 2009 From: resistor at mac.com (Owen Anderson) Date: Wed, 22 Apr 2009 08:46:52 -0000 Subject: [llvm-commits] [llvm] r69791 - /llvm/trunk/include/llvm/Support/PredIteratorCache.h Message-ID: <200904220846.n3M8krqT001386@zion.cs.uiuc.edu> Author: resistor Date: Wed Apr 22 03:46:33 2009 New Revision: 69791 URL: http://llvm.org/viewvc/llvm-project?rev=69791&view=rev Log: Add caching of predecessor counts as well as predecessors themselves. Modified: llvm/trunk/include/llvm/Support/PredIteratorCache.h Modified: llvm/trunk/include/llvm/Support/PredIteratorCache.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/PredIteratorCache.h?rev=69791&r1=69790&r2=69791&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/PredIteratorCache.h (original) +++ llvm/trunk/include/llvm/Support/PredIteratorCache.h Wed Apr 22 03:46:33 2009 @@ -27,6 +27,7 @@ class PredIteratorCache { /// BlockToPredsMap - Pointer to null-terminated list. DenseMap BlockToPredsMap; + DenseMap BlockToPredCountMap; /// Memory - This is the space that holds cached preds. BumpPtrAllocator Memory; @@ -44,15 +45,23 @@ SmallVector PredCache(pred_begin(BB), pred_end(BB)); PredCache.push_back(0); // null terminator. + + BlockToPredCountMap[BB] = PredCache.size()-1; Entry = Memory.Allocate(PredCache.size()); std::copy(PredCache.begin(), PredCache.end(), Entry); return Entry; } + + unsigned GetNumPreds(BasicBlock *BB) { + GetPreds(BB); + return BlockToPredCountMap[BB]; + } /// clear - Remove all information. void clear() { BlockToPredsMap.clear(); + BlockToPredCountMap.clear(); Memory.Reset(); } }; From resistor at mac.com Wed Apr 22 03:50:28 2009 From: resistor at mac.com (Owen Anderson) Date: Wed, 22 Apr 2009 08:50:28 -0000 Subject: [llvm-commits] [llvm] r69792 - /llvm/trunk/lib/Transforms/Utils/LCSSA.cpp Message-ID: <200904220850.n3M8oU56001522@zion.cs.uiuc.edu> Author: resistor Date: Wed Apr 22 03:50:12 2009 New Revision: 69792 URL: http://llvm.org/viewvc/llvm-project?rev=69792&view=rev Log: Real fix for PR3549, by using caching for predecessor counts in addition to the predecessors themselves. This halves the time to optimize the testcase, beyond what my previous patch did. Modified: llvm/trunk/lib/Transforms/Utils/LCSSA.cpp Modified: llvm/trunk/lib/Transforms/Utils/LCSSA.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LCSSA.cpp?rev=69792&r1=69791&r2=69792&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/LCSSA.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/LCSSA.cpp Wed Apr 22 03:50:12 2009 @@ -86,7 +86,8 @@ } private: void getLoopValuesUsedOutsideLoop(Loop *L, - SetVector &AffectedValues); + SetVector &AffectedValues, + const SmallVector& exitBlocks); Value *GetValueForBlock(DomTreeNode *BB, Instruction *OrigInst, DenseMap &Phis); @@ -116,17 +117,17 @@ LoopBlocks.insert(LoopBlocks.end(), L->block_begin(), L->block_end()); std::sort(LoopBlocks.begin(), LoopBlocks.end()); + SmallVector exitBlocks; + L->getExitBlocks(exitBlocks); + SetVector AffectedValues; - getLoopValuesUsedOutsideLoop(L, AffectedValues); + getLoopValuesUsedOutsideLoop(L, AffectedValues, exitBlocks); // If no values are affected, we can save a lot of work, since we know that // nothing will be changed. if (AffectedValues.empty()) return false; - SmallVector exitBlocks; - L->getExitBlocks(exitBlocks); - // Iterate over all affected values for this loop and insert Phi nodes // for them in the appropriate exit blocks @@ -160,7 +161,7 @@ if (!Phi && DT->dominates(InstrNode, ExitBBNode)) { PHINode *PN = PHINode::Create(Instr->getType(), Instr->getName()+".lcssa", BB->begin()); - PN->reserveOperandSpace(std::distance(pred_begin(BB), pred_end(BB))); + PN->reserveOperandSpace(PredCache.GetNumPreds(BB)); // Remember that this phi makes the value alive in this block. Phi = PN; @@ -202,15 +203,16 @@ /// getLoopValuesUsedOutsideLoop - Return any values defined in the loop that /// are used by instructions outside of it. void LCSSA::getLoopValuesUsedOutsideLoop(Loop *L, - SetVector &AffectedValues) { + SetVector &AffectedValues, + const SmallVector& exitBlocks) { // FIXME: For large loops, we may be able to avoid a lot of use-scanning // by using dominance information. In particular, if a block does not // dominate any of the loop exits, then none of the values defined in the // block could be used outside the loop. - for (Loop::block_iterator BB = L->block_begin(), E = L->block_end(); - BB != E; ++BB) { + for (Loop::block_iterator BB = L->block_begin(), BE = L->block_end(); + BB != BE; ++BB) { for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I != E; ++I) - for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; + for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE; ++UI) { BasicBlock *UserBB = cast(*UI)->getParent(); if (PHINode* p = dyn_cast(*UI)) { @@ -263,7 +265,7 @@ // now, then get values to fill in the incoming values for the PHI. PHINode *PN = PHINode::Create(OrigInst->getType(), OrigInst->getName() + ".lcssa", BBN->begin()); - PN->reserveOperandSpace(std::distance(pred_begin(BBN), pred_end(BBN))); + PN->reserveOperandSpace(PredCache.GetNumPreds(BBN)); Phis.insert(std::make_pair(BB, PN)); // Fill in the incoming values for the block. From baldrick at free.fr Wed Apr 22 04:28:23 2009 From: baldrick at free.fr (Duncan Sands) Date: Wed, 22 Apr 2009 09:28:23 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r69795 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Message-ID: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu> Author: baldrick Date: Wed Apr 22 04:27:52 2009 New Revision: 69795 URL: http://llvm.org/viewvc/llvm-project?rev=69795&view=rev Log: Chris's new record constructor code broke the x86-32 Ada build because it doesn't handle the case when the size of a field is less than the size of the type of the field. Fix by truncating the initial value in this case. It may be that this is only valid if the discarded bits are zero, but I'm not sure so I didn't add a check for this. 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=69795&r1=69794&r2=69795&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Wed Apr 22 04:27:52 2009 @@ -6771,15 +6771,15 @@ /// lay out struct inits. struct ConstantLayoutInfo { const TargetData &TD; - + /// ResultElts - The initializer elements so far. std::vector ResultElts; - + /// StructIsPacked - This is set to true if we find out that we have to emit /// the ConstantStruct as a Packed LLVM struct type (because the LLVM /// alignment rules would prevent laying out the struct correctly). bool StructIsPacked; - + /// NextFieldByteStart - This field indicates the *byte* that the next field /// will start at. Put another way, this is the size of the struct as /// currently laid out, but without any tail padding considered. @@ -6788,21 +6788,21 @@ /// MaxLLVMFieldAlignment - This is the largest alignment of any IR field, /// which is the alignment that the ConstantStruct will get. unsigned MaxLLVMFieldAlignment; - - + + ConstantLayoutInfo(const TargetData &TD) : TD(TD) { StructIsPacked = false; NextFieldByteStart = 0; MaxLLVMFieldAlignment = 1; } - + void ConvertToPacked(); void AddFieldToRecordConstant(Constant *Val, uint64_t GCCFieldOffsetInBits); void AddBitFieldToRecordConstant(ConstantInt *Val, uint64_t GCCFieldOffsetInBits); void HandleTailPadding(uint64_t GCCStructBitSize); }; - + } /// ConvertToPacked - Given a partially constructed initializer for a LLVM @@ -6812,19 +6812,19 @@ uint64_t EltOffs = 0; for (unsigned i = 0, e = ResultElts.size(); i != e; ++i) { Constant *Val = ResultElts[i]; - + // Check to see if this element has an alignment that would cause it to get // offset. If so, insert explicit padding for the offset. unsigned ValAlign = TD.getABITypeAlignment(Val->getType()); uint64_t AlignedEltOffs = TargetData::RoundUpAlignment(EltOffs, ValAlign); - + // If the alignment doesn't affect the element offset, then the value is ok. // Accept the field and keep moving. if (AlignedEltOffs == EltOffs) { EltOffs += TD.getTypePaddedSize(Val->getType()); continue; } - + // Otherwise, there is padding here. Insert explicit zeros. const Type *PadTy = Type::Int8Ty; if (AlignedEltOffs-EltOffs != 1) @@ -6832,7 +6832,7 @@ ResultElts.insert(ResultElts.begin()+i, Constant::getNullValue(PadTy)); ++e; // One extra element to scan. } - + // Packed now! MaxLLVMFieldAlignment = 1; StructIsPacked = true; @@ -6848,13 +6848,13 @@ /// The arguments are: /// Val: The value to add to the struct, with a size that matches the size of /// the corresponding GCC field. -/// GCCFieldOffsetInBits: The offset that we have to put Val in the result. +/// GCCFieldOffsetInBits: The offset that we have to put Val in the result. /// void ConstantLayoutInfo:: AddFieldToRecordConstant(Constant *Val, uint64_t GCCFieldOffsetInBits) { assert((TD.getTypeSizeInBits(Val->getType()) & 7) == 0 && "Cannot handle non-byte sized values"); - + // Figure out how to add this non-bitfield value to our constant struct so // that it ends up at the right offset. There are four cases we have to // think about: @@ -6870,27 +6870,27 @@ // field. // Start by determining which case we have by looking at where LLVM and GCC // would place the field. - + // Verified that we haven't already laid out bytes that will overlap with // this new field. assert(NextFieldByteStart*8 <= GCCFieldOffsetInBits && "Overlapping LLVM fields!"); - + // Compute the offset the field would get if we just stuck 'Val' onto the // end of our structure right now. It is NextFieldByteStart rounded up to // the LLVM alignment of Val's type. unsigned ValLLVMAlign = 1; - + if (!StructIsPacked) { // Packed structs ignore the alignment of members. ValLLVMAlign = TD.getABITypeAlignment(Val->getType()); MaxLLVMFieldAlignment = std::max(MaxLLVMFieldAlignment, ValLLVMAlign); } - + // LLVMNaturalByteOffset - This is where LLVM would drop the field if we // slap it onto the end of the struct. uint64_t LLVMNaturalByteOffset = TargetData::RoundUpAlignment(NextFieldByteStart, ValLLVMAlign); - + // If adding the LLVM field would push it over too far, then we must have a // case that requires the LLVM struct to be packed. Do it now if so. if (LLVMNaturalByteOffset*8 > GCCFieldOffsetInBits) { @@ -6900,7 +6900,7 @@ assert(LLVMNaturalByteOffset*8 <= GCCFieldOffsetInBits && "Packing didn't fix the problem!"); } - + // If the LLVM offset is not large enough, we need to insert explicit // padding in the LLVM struct between the fields. if (LLVMNaturalByteOffset*8 < GCCFieldOffsetInBits) { @@ -6912,12 +6912,12 @@ FillTy = ArrayType::get(FillTy, GCCFieldOffsetInBits/8-NextFieldByteStart); ResultElts.push_back(Constant::getNullValue(FillTy)); - + NextFieldByteStart = GCCFieldOffsetInBits/8; LLVMNaturalByteOffset = TargetData::RoundUpAlignment(NextFieldByteStart, ValLLVMAlign); } - + // Slap 'Val' onto the end of our ConstantStruct, it must be known to land // at the right offset now. assert(LLVMNaturalByteOffset*8 == GCCFieldOffsetInBits); @@ -6939,7 +6939,7 @@ ResultElts.push_back(ConstantInt::get(Type::Int8Ty, 0)); ++NextFieldByteStart; } - + // If the field is a bitfield, it could partially go in a previously // laid out structure member, and may add elements to the end of the currently // laid out structure. @@ -6951,7 +6951,7 @@ // bitfields can only be initialized by ConstantInts. An interesting case is // sharing of tail padding in C++ structures. Because this can only happen // in inheritance cases, and those are non-POD, we should never see them here. - + // First handle any part of Val that overlaps an already laid out field by // merging it into it. By the above invariants, we know that it is an i8 that // we are merging into. Note that we may be inserting *all* of Val into the @@ -6970,7 +6970,7 @@ unsigned BitsInPreviousField = unsigned(NextFieldByteStart*8 - GCCFieldOffsetInBits); assert(BitsInPreviousField != 0 && "Previous field should not be null!"); - + // Split the bits that will be inserted into the previous element out of // Val into a new constant. If Val is completely contained in the previous // element, this sets Val to null, otherwise we shrink Val to contain the @@ -6990,12 +6990,12 @@ // Big endian, take bits from the top of the field value. ValForPrevField = ValForPrevField.lshr(ValBitSize-BitsInPreviousField); ValForPrevField.trunc(BitsInPreviousField); - + APInt Tmp = ValC->getValue(); Tmp = Tmp.trunc(ValBitSize-BitsInPreviousField); ValC = ConstantInt::get(Tmp); } - + // Okay, we're going to insert ValForPrevField into the previous i8, extend // it and shift into place. ValForPrevField.zext(8); @@ -7007,16 +7007,16 @@ if (BitsInPreviousField > ValBitSize) ValForPrevField = ValForPrevField.shl(BitsInPreviousField-ValBitSize); } - + // "or" in the previous value and install it. const APInt &LastElt = cast(ResultElts.back())->getValue(); ResultElts.back() = ConstantInt::get(ValForPrevField | LastElt); - + // If the whole bit-field fit into the previous field, we're done. if (ValC == 0) return; GCCFieldOffsetInBits = NextFieldByteStart*8; } - + APInt Val = ValC->getValue(); // Okay, we know that we're plopping bytes onto the end of the struct. @@ -7029,7 +7029,7 @@ APInt Tmp = Val; Tmp.trunc(8); ValToAppend = ConstantInt::get(Tmp); - + Val = Val.lshr(8); } else { // Big endian lays out high bits first. @@ -7043,15 +7043,15 @@ } else { APInt Tmp = Val; Tmp.zext(8); - + if (BYTES_BIG_ENDIAN) Tmp = Tmp << 8-Val.getBitWidth(); ValToAppend = ConstantInt::get(Tmp); } - + ResultElts.push_back(ValToAppend); ++NextFieldByteStart; - + if (Val.getBitWidth() <= 8) break; Val.trunc(Val.getBitWidth()-8); @@ -7068,7 +7068,7 @@ uint64_t GCCStructSize = (GCCStructBitSize+7)/8; uint64_t LLVMNaturalSize = TargetData::RoundUpAlignment(NextFieldByteStart, MaxLLVMFieldAlignment); - + // If the total size of the laid out data is within the size of the GCC type // but the rounded-up size (including the tail padding induced by LLVM // alignment) is too big, convert to a packed struct type. We don't do this @@ -7080,16 +7080,16 @@ if (NextFieldByteStart <= GCCStructSize && // Not flexible init case. LLVMNaturalSize > GCCStructSize) { // Tail pad will overflow type. assert(!StructIsPacked && "LLVM Struct type overflow!"); - + // Switch to packed. ConvertToPacked(); LLVMNaturalSize = NextFieldByteStart; - + // Verify that packing solved the problem. assert(LLVMNaturalSize <= GCCStructSize && "Oversized should be handled by packing"); } - + // If the LLVM Size is too small, add some tail padding to fill it in. if (LLVMNaturalSize < GCCStructSize) { const Type *FillTy = Type::Int8Ty; @@ -7101,7 +7101,7 @@ Constant *TreeConstantToLLVM::ConvertRecordCONSTRUCTOR(tree exp) { ConstantLayoutInfo LayoutInfo(getTargetData()); - + tree NextField = TYPE_FIELDS(TREE_TYPE(exp)); unsigned HOST_WIDE_INT CtorIndex; tree FieldValue; @@ -7118,14 +7118,14 @@ Field = TREE_CHAIN(Field); } } - + // Decode the field's value. Constant *Val = Convert(FieldValue); - + // GCCFieldOffsetInBits is where GCC is telling us to put the current field. uint64_t GCCFieldOffsetInBits = getFieldOffsetInBits(Field); NextField = TREE_CHAIN(Field); - + // If this is a non-bitfield value, just slap it onto the end of the struct // with the appropriate padding etc. If it is a bitfield, we have more @@ -7134,14 +7134,21 @@ LayoutInfo.AddFieldToRecordConstant(Val, GCCFieldOffsetInBits); else { assert(isa(Val) && "Can only init bitfield with constant"); - assert(Val->getType()->getPrimitiveSizeInBits() == - TREE_INT_CST_LOW(DECL_SIZE(Field)) && + uint64_t FieldSizeInBits = getInt64(DECL_SIZE(Field), true); + uint64_t ValueSizeInBits = Val->getType()->getPrimitiveSizeInBits(); + assert(ValueSizeInBits >= FieldSizeInBits && "disagreement between LLVM and GCC on bitfield size"); + if (ValueSizeInBits != FieldSizeInBits) { + // Fields are allowed to be smaller than their type. Simply discard + // the unwanted upper bits in the field value. + APInt ValAsInt = cast(Val)->getValue(); + Val = ConstantInt::get(ValAsInt.trunc(FieldSizeInBits)); + } LayoutInfo.AddBitFieldToRecordConstant(cast(Val), GCCFieldOffsetInBits); } } - + // Check to see if the struct fields, as laid out so far, will be large enough // to make the generated constant struct have the right size. If not, add // explicit tail padding. If rounding up based on the LLVM IR alignment would @@ -7149,7 +7156,7 @@ tree StructTypeSizeTree = TYPE_SIZE(TREE_TYPE(exp)); if (StructTypeSizeTree && TREE_CODE(StructTypeSizeTree) == INTEGER_CST) LayoutInfo.HandleTailPadding(getInt64(StructTypeSizeTree, true)); - + // Okay, we're done, return the computed elements. return ConstantStruct::get(LayoutInfo.ResultElts, LayoutInfo.StructIsPacked); } From baldrick at free.fr Wed Apr 22 05:40:10 2009 From: baldrick at free.fr (Duncan Sands) Date: Wed, 22 Apr 2009 10:40:10 -0000 Subject: [llvm-commits] [llvm] r69798 - in /llvm/trunk/test: FrontendC/2009-01-20-k8.c FrontendFortran/2008-11-03-OptionOverride.f90 Message-ID: <200904221040.n3MAeCQH007343@zion.cs.uiuc.edu> Author: baldrick Date: Wed Apr 22 05:39:51 2009 New Revision: 69798 URL: http://llvm.org/viewvc/llvm-project?rev=69798&view=rev Log: These tests are x86 specific. Modified: llvm/trunk/test/FrontendC/2009-01-20-k8.c llvm/trunk/test/FrontendFortran/2008-11-03-OptionOverride.f90 Modified: llvm/trunk/test/FrontendC/2009-01-20-k8.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/2009-01-20-k8.c?rev=69798&r1=69797&r2=69798&view=diff ============================================================================== --- llvm/trunk/test/FrontendC/2009-01-20-k8.c (original) +++ llvm/trunk/test/FrontendC/2009-01-20-k8.c Wed Apr 22 05:39:51 2009 @@ -1,2 +1,3 @@ // RUN: %llvmgcc %s -S -march=k8 +// XTARGET: x86 long double x; Modified: llvm/trunk/test/FrontendFortran/2008-11-03-OptionOverride.f90 URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendFortran/2008-11-03-OptionOverride.f90?rev=69798&r1=69797&r2=69798&view=diff ============================================================================== --- llvm/trunk/test/FrontendFortran/2008-11-03-OptionOverride.f90 (original) +++ llvm/trunk/test/FrontendFortran/2008-11-03-OptionOverride.f90 Wed Apr 22 05:39:51 2009 @@ -1,3 +1,4 @@ ! RUN: %llvmgcc -c %s -march=k8 +! XTARGET: x86 ! Note: this file intentionally left blank, the problem itself is in -! frontend initialization routines and march flag! \ No newline at end of file +! frontend initialization routines and march flag! From sanjiv.gupta at microchip.com Wed Apr 22 06:53:54 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Wed, 22 Apr 2009 17:23:54 +0530 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <200904210952.19433.baldrick@free.fr> References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> <200904210732.32368.baldrick@free.fr> <49ED6C3A.8070909@microchip.com> <200904210952.19433.baldrick@free.fr> Message-ID: <49EF0552.8050807@microchip.com> Duncan Sands wrote: > Hi Sanjiv, > > >>>>>> Before trying to introduce/eliminate cast/ext/trunc to make indices type as >>>>>> pointer type, make sure that the pointer size is a valid sequential index type. >>>>>> >>>>>> >>> I think a better approach would be to add a "get preferred type for GEP indices" >>> method to TargetData. This would return getIntPtrType on most targets, and i16 >>> on PIC16. Then change this transform to use the type given by that method rather >>> than getIntPtrType. >>> >>> >> I think you meant i32 on PIC16, because i16 indices are still not >> allowed to GEP. >> > > sure, if that's what PIC16 wants. Anyway, the point is to decouple the GEP index > type from pointer types in a clean way, by introducing new abstractions. > > Ciao, > > Duncan. > This whole thing is actually a work around for r58505. i16 indices would be great for pic16 as they won't deny such inst combine optimization to it. When I fix that up this thing here and corresponding things in clang will not be needed. From sanjiv.gupta at microchip.com Wed Apr 22 07:03:06 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Wed, 22 Apr 2009 12:03:06 -0000 Subject: [llvm-commits] [llvm] r69801 - in /llvm/trunk/lib/Target/PIC16: PIC16AsmPrinter.cpp PIC16ISelLowering.cpp PIC16InstrInfo.td Message-ID: <200904221203.n3MC3AGK010170@zion.cs.uiuc.edu> Author: sgupta Date: Wed Apr 22 07:02:36 2009 New Revision: 69801 URL: http://llvm.org/viewvc/llvm-project?rev=69801&view=rev Log: Make the function begin label start after ther data pointer. The address of data frame for function can be obtained by subtracting 2 from the function begin label. Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp?rev=69801&r1=69800&r2=69801&view=diff ============================================================================== --- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp (original) +++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Wed Apr 22 07:02:36 2009 @@ -116,9 +116,9 @@ SwitchToSection (fCodeSection); // Emit the frame address of the function at the beginning of code. - O << CurrentFnName << ":\n"; O << " retlw low(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n"; O << " retlw high(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n"; + O << CurrentFnName << ":\n"; // Print out code for the function. Modified: llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp?rev=69801&r1=69800&r2=69801&view=diff ============================================================================== --- llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp Wed Apr 22 07:02:36 2009 @@ -1155,10 +1155,12 @@ SDValue Lo = Callee.getOperand(0); SDValue Hi = Callee.getOperand(1); + SDValue Data_Lo, Data_Hi; SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag); Hi = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, Hi); - // Use the Lo part as is and make CALLW - Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Lo, Hi); + // Subtract 2 from Lo to get the Lower part of DataAddress. + Data_Lo = DAG.getNode(ISD::SUB, dl, MVT::i8, Lo, DAG.getConstant(2, MVT::i8)); + Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Data_Lo, Hi); SDValue Call = DAG.getNode(PIC16ISD::CALLW, dl, Tys, Chain, Callee, OperFlag); Chain = getChain(Call); @@ -1176,10 +1178,10 @@ Chain = getChain(SeqStart); OperFlag = getOutFlag(SeqStart); // To manage the data dependency - // Add 1 to Lo part for the second code word. - Lo = DAG.getNode(ISD::ADD, dl, MVT::i8, Lo, DAG.getConstant(1, MVT::i8)); + // Subtract 1 to Lo part for the second code word. + Data_Lo = DAG.getNode(ISD::SUB, dl, MVT::i8, Lo, DAG.getConstant(1, MVT::i8)); // Use new Lo to make another CALLW - Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Lo, Hi); + Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Data_Lo, Hi); Call = DAG.getNode(PIC16ISD::CALLW, dl, Tys, Chain, Callee, OperFlag); Chain = getChain(Call); OperFlag = getOutFlag(Call); @@ -1266,8 +1268,8 @@ SDValue CodeAddr_Lo = Callee.getOperand(0); SDValue CodeAddr_Hi = Callee.getOperand(1); - CodeAddr_Lo = DAG.getNode(ISD::ADD, dl, MVT::i8, CodeAddr_Lo, - DAG.getConstant(2, MVT::i8)); + /*CodeAddr_Lo = DAG.getNode(ISD::ADD, dl, MVT::i8, CodeAddr_Lo, + DAG.getConstant(2, MVT::i8));*/ // move Hi part in PCLATH CodeAddr_Hi = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, CodeAddr_Hi); Modified: llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td?rev=69801&r1=69800&r2=69801&view=diff ============================================================================== --- llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td (original) +++ llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td Wed Apr 22 07:02:36 2009 @@ -428,7 +428,8 @@ let isCall = 1, Defs = [W, FSR0, FSR1] in { def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func), - "call ${func} + 2", + //"call ${func} + 2", + "call ${func}", [(PIC16call diraddr:$func)]>; } From gohman at apple.com Wed Apr 22 10:55:51 2009 From: gohman at apple.com (Dan Gohman) Date: Wed, 22 Apr 2009 15:55:51 -0000 Subject: [llvm-commits] [llvm] r69804 - /llvm/trunk/docs/CodeGenerator.html Message-ID: <200904221556.n3MFtxnG018935@zion.cs.uiuc.edu> Author: djg Date: Wed Apr 22 10:55:31 2009 New Revision: 69804 URL: http://llvm.org/viewvc/llvm-project?rev=69804&view=rev Log: ISD::ADD_PARTS is gone; use ISD::SMUL_LOHI as an example instead. Modified: llvm/trunk/docs/CodeGenerator.html Modified: llvm/trunk/docs/CodeGenerator.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CodeGenerator.html?rev=69804&r1=69803&r2=69804&view=diff ============================================================================== --- llvm/trunk/docs/CodeGenerator.html (original) +++ llvm/trunk/docs/CodeGenerator.html Wed Apr 22 10:55:31 2009 @@ -1161,7 +1161,7 @@

Note that all of the values have rules specifying how they convert to values @@ -627,8 +632,9 @@

The name of the resultant definitions has the multidef fragment names appended to them, so this defines ADD_rr, ADD_ri, - SUB_rr, etc. Using a multiclass this way is exactly equivalent to - instantiating the classes multiple times yourself, e.g. by writing:

+ SUB_rr, etc. Using a multiclass this way is exactly + equivalent to instantiating the classes multiple times yourself, + e.g. by writing:


Added: llvm/trunk/test/TableGen/nameconcat.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/nameconcat.td?rev=69822&view=auto

==============================================================================
--- llvm/trunk/test/TableGen/nameconcat.td (added)
+++ llvm/trunk/test/TableGen/nameconcat.td Wed Apr 22 15:18:10 2009
@@ -0,0 +1,76 @@
+// RUN: tblgen %s | grep {add_ps} | count 2
+
+class ValueType {
+  int Size = size;
+  int Value = value;
+}
+
+def v2i64  : ValueType<128, 22>;   //  2 x i64 vector value
+def v2f64  : ValueType<128, 28>;   //  2 x f64 vector value
+
+class Intrinsic {
+  string Name = name;
+}
+
+class Inst opcode, dag oopnds, dag iopnds, string asmstr, 
+           list pattern> {
+  bits<8> Opcode = opcode;
+  dag OutOperands = oopnds;
+  dag InOperands = iopnds;
+  string AssemblyString = asmstr;
+  list Pattern = pattern;
+}
+
+def ops;
+def outs;
+def ins;
+
+def set;
+
+// Define registers
+class Register {
+  string Name = n;
+}
+
+class RegisterClass regTypes, list regList> {
+  list RegTypes = regTypes;
+  list MemberList = regList;
+}
+
+def XMM0: Register<"xmm0">;
+def XMM1: Register<"xmm1">;
+def XMM2: Register<"xmm2">;
+def XMM3: Register<"xmm3">;
+def XMM4: Register<"xmm4">;
+def XMM5: Register<"xmm5">;
+def XMM6: Register<"xmm6">;
+def XMM7: Register<"xmm7">;
+def XMM8:  Register<"xmm8">;
+def XMM9:  Register<"xmm9">;
+def XMM10: Register<"xmm10">;
+def XMM11: Register<"xmm11">;
+def XMM12: Register<"xmm12">;
+def XMM13: Register<"xmm13">;
+def XMM14: Register<"xmm14">;
+def XMM15: Register<"xmm15">;
+
+def VR128 : RegisterClass<[v2i64, v2f64],
+                          [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
+                           XMM8, XMM9, XMM10, XMM11,
+                           XMM12, XMM13, XMM14, XMM15]>;
+
+// Define intrinsics
+def int_x86_sse2_add_ps : Intrinsic<"addps">;
+def int_x86_sse2_add_pd : Intrinsic<"addpd">;
+
+multiclass arith opcode, string asmstr, string Intr> {
+  def PS : Inst;
+
+  def PD : Inst;
+}
+
+defm ADD : arith<0x58, "add", "int_x86_sse2_add">;

Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.cpp?rev=69822&r1=69821&r2=69822&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenInstruction.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenInstruction.cpp Wed Apr 22 15:18:10 2009
@@ -127,7 +127,7 @@
     OperandList.clear();
     return;
   }
-  DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold();
+  DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold(R, 0);
 
   unsigned MIOperandNo = 0;
   std::set OperandNames;

Modified: llvm/trunk/utils/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.cpp?rev=69822&r1=69821&r2=69822&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/Record.cpp (original)
+++ llvm/trunk/utils/TableGen/Record.cpp Wed Apr 22 15:18:10 2009
@@ -395,7 +395,7 @@
   return Result + "]";
 }
 
-Init *BinOpInit::Fold() {
+Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
   switch (getOpcode()) {
   default: assert(0 && "Unknown binop");
   case CONCAT: {
@@ -437,6 +437,43 @@
       return new StringInit(LHSs->getValue() + RHSs->getValue());
     break;
   }
+  case NAMECONCAT: {
+    StringInit *LHSs = dynamic_cast(LHS);
+    StringInit *RHSs = dynamic_cast(RHS);
+    if (LHSs && RHSs) {
+      std::string Name(LHSs->getValue() + RHSs->getValue());
+
+      // From TGParser::ParseIDValue
+      if (CurRec) {
+        if (const RecordVal *RV = CurRec->getValue(Name))
+          return new VarInit(Name, RV->getType());
+
+        std::string TemplateArgName = CurRec->getName()+":"+Name;
+        if (CurRec->isTemplateArg(TemplateArgName)) {
+          const RecordVal *RV = CurRec->getValue(TemplateArgName);
+          assert(RV && "Template arg doesn't exist??");
+          return new VarInit(TemplateArgName, RV->getType());
+        }
+      }
+
+      if (CurMultiClass) {
+        std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
+        if (CurMultiClass->Rec.isTemplateArg(MCName)) {
+          const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
+          assert(RV && "Template arg doesn't exist??");
+          return new VarInit(MCName, RV->getType());
+        }
+      }
+
+      if (Record *D = Records.getDef(Name))
+        return new DefInit(D);
+
+      cerr << "Variable not defined: '" + Name + "'\n";
+      assert(0 && "Variable not found");
+      return 0;
+    }
+    break;
+  }
   case SHL:
   case SRA:
   case SRL: {
@@ -464,8 +501,8 @@
   Init *rhs = RHS->resolveReferences(R, RV);
   
   if (LHS != lhs || RHS != rhs)
-    return (new BinOpInit(getOpcode(), lhs, rhs))->Fold();
-  return Fold();
+    return (new BinOpInit(getOpcode(), lhs, rhs))->Fold(&R, 0);
+  return Fold(&R, 0);
 }
 
 std::string BinOpInit::getAsString() const {
@@ -476,6 +513,7 @@
   case SRA: Result = "!sra"; break;
   case SRL: Result = "!srl"; break;
   case STRCONCAT: Result = "!strconcat"; break;
+  case NAMECONCAT: Result = "!nameconcat"; break;
   }
   return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
 }

Modified: llvm/trunk/utils/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.h?rev=69822&r1=69821&r2=69822&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/Record.h (original)
+++ llvm/trunk/utils/TableGen/Record.h Wed Apr 22 15:18:10 2009
@@ -53,6 +53,7 @@
 // Other classes.
 class Record;
 class RecordVal;
+class MultiClass;
 
 //===----------------------------------------------------------------------===//
 //  Type Classes
@@ -659,7 +660,7 @@
 ///
 class BinOpInit : public Init {
 public:
-  enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT };
+  enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, NAMECONCAT };
 private:
   BinaryOp Opc;
   Init *LHS, *RHS;
@@ -673,7 +674,7 @@
 
   // Fold - If possible, fold this to a simpler init.  Return this if not
   // possible to fold.
-  Init *Fold();
+  Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
 
   virtual Init *convertInitializerTo(RecTy *Ty) {
     return Ty->convertValue(this);
@@ -1124,6 +1125,14 @@
 
 std::ostream &operator<<(std::ostream &OS, const Record &R);
 
+struct MultiClass {
+  Record Rec;  // Placeholder for template args and Name.
+  typedef std::vector RecordVector;
+  RecordVector DefPrototypes;
+    
+  MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {}
+};
+
 class RecordKeeper {
   std::map Classes, Defs;
 public:

Modified: llvm/trunk/utils/TableGen/TGLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGLexer.cpp?rev=69822&r1=69821&r2=69822&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TGLexer.cpp (original)
+++ llvm/trunk/utils/TableGen/TGLexer.cpp Wed Apr 22 15:18:10 2009
@@ -429,11 +429,12 @@
   // Check to see which operator this is.
   unsigned Len = CurPtr-Start;
   
-  if (Len == 3 && !memcmp(Start, "con", 3)) return tgtok::XConcat;
-  if (Len == 3 && !memcmp(Start, "sra", 3)) return tgtok::XSRA;
-  if (Len == 3 && !memcmp(Start, "srl", 3)) return tgtok::XSRL;
-  if (Len == 3 && !memcmp(Start, "shl", 3)) return tgtok::XSHL;
-  if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat;
+  if (Len == 3  && !memcmp(Start, "con", 3)) return tgtok::XConcat;
+  if (Len == 3  && !memcmp(Start, "sra", 3)) return tgtok::XSRA;
+  if (Len == 3  && !memcmp(Start, "srl", 3)) return tgtok::XSRL;
+  if (Len == 3  && !memcmp(Start, "shl", 3)) return tgtok::XSHL;
+  if (Len == 9  && !memcmp(Start, "strconcat", 9))   return tgtok::XStrConcat;
+  if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat;
   
   return ReturnError(Start-1, "Unknown operator");
 }

Modified: llvm/trunk/utils/TableGen/TGLexer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGLexer.h?rev=69822&r1=69821&r2=69822&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TGLexer.h (original)
+++ llvm/trunk/utils/TableGen/TGLexer.h Wed Apr 22 15:18:10 2009
@@ -45,8 +45,8 @@
     MultiClass, String,
     
     // !keywords.
-    XConcat, XSRA, XSRL, XSHL, XStrConcat,
-    
+    XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat,
+
     // Integer value.
     IntVal,
     

Modified: llvm/trunk/utils/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.cpp?rev=69822&r1=69821&r2=69822&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TGParser.cpp (original)
+++ llvm/trunk/utils/TableGen/TGParser.cpp Wed Apr 22 15:18:10 2009
@@ -23,14 +23,6 @@
 //===----------------------------------------------------------------------===//
 
 namespace llvm {
-struct MultiClass {
-  Record Rec;  // Placeholder for template args and Name.
-  typedef std::vector RecordVector;
-  RecordVector DefPrototypes;
-    
-  MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {}
-};
-  
 struct SubClassReference {
   TGLoc RefLoc;
   Record *Rec;
@@ -777,14 +769,47 @@
   }
   case tgtok::l_paren: {         // Value ::= '(' IDValue DagArgList ')'
     Lex.Lex();   // eat the '('
-    if (Lex.getCode() != tgtok::Id) {
+    if (Lex.getCode() != tgtok::Id
+        && Lex.getCode() != tgtok::XNameConcat) {
       TokError("expected identifier in dag init");
       return 0;
     }
     
-    Init *Operator = ParseIDValue(CurRec);
-    if (Operator == 0) return 0;
-    
+    Init *Operator = 0;
+    if (Lex.getCode() == tgtok::Id) {
+      Operator = ParseIDValue(CurRec);
+      if (Operator == 0) return 0;
+    }
+    else {
+      BinOpInit::BinaryOp Code = BinOpInit::NAMECONCAT;
+ 
+      Lex.Lex();  // eat the operation
+      if (Lex.getCode() != tgtok::l_paren) {
+        TokError("expected '(' after binary operator");
+        return 0;
+      }
+      Lex.Lex();  // eat the '('
+
+      Init *LHS = ParseValue(CurRec);
+      if (LHS == 0) return 0;
+
+      if (Lex.getCode() != tgtok::comma) {
+        TokError("expected ',' in binary operator");
+        return 0;
+      }
+      Lex.Lex();  // eat the ','
+
+      Init *RHS = ParseValue(CurRec);
+       if (RHS == 0) return 0;
+
+       if (Lex.getCode() != tgtok::r_paren) {
+         TokError("expected ')' in binary operator");
+         return 0;
+       }
+       Lex.Lex();  // eat the ')'
+       Operator = (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass);
+    }
+
     // If the operator name is present, parse it.
     std::string OperatorName;
     if (Lex.getCode() == tgtok::colon) {
@@ -796,7 +821,6 @@
       Lex.Lex();  // eat the VarName.
     }
     
-    
     std::vector > DagArgs;
     if (Lex.getCode() != tgtok::r_paren) {
       DagArgs = ParseDagArgList(CurRec);
@@ -815,15 +839,17 @@
   case tgtok::XSRA: 
   case tgtok::XSRL:
   case tgtok::XSHL:
-  case tgtok::XStrConcat: {  // Value ::= !binop '(' Value ',' Value ')'
+  case tgtok::XStrConcat:
+  case tgtok::XNameConcat: {  // Value ::= !binop '(' Value ',' Value ')'
     BinOpInit::BinaryOp Code;
     switch (Lex.getCode()) {
     default: assert(0 && "Unhandled code!");
-    case tgtok::XConcat:    Code = BinOpInit::CONCAT; break;
-    case tgtok::XSRA:       Code = BinOpInit::SRA; break;
-    case tgtok::XSRL:       Code = BinOpInit::SRL; break;
-    case tgtok::XSHL:       Code = BinOpInit::SHL; break;
-    case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break;
+    case tgtok::XConcat:     Code = BinOpInit::CONCAT; break;
+    case tgtok::XSRA:        Code = BinOpInit::SRA; break;
+    case tgtok::XSRL:        Code = BinOpInit::SRL; break;
+    case tgtok::XSHL:        Code = BinOpInit::SHL; break;
+    case tgtok::XStrConcat:  Code = BinOpInit::STRCONCAT; break;
+    case tgtok::XNameConcat: Code = BinOpInit::NAMECONCAT; break;
     }
     Lex.Lex();  // eat the operation
     if (Lex.getCode() != tgtok::l_paren) {
@@ -831,7 +857,7 @@
       return 0;
     }
     Lex.Lex();  // eat the '('
-    
+
     Init *LHS = ParseValue(CurRec);
     if (LHS == 0) return 0;
 
@@ -849,7 +875,7 @@
       return 0;
     }
     Lex.Lex();  // eat the ')'
-    return (new BinOpInit(Code, LHS, RHS))->Fold();
+    return (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass);
   }
   }
   




From gohman at apple.com  Wed Apr 22 15:54:18 2009
From: gohman at apple.com (Dan Gohman)
Date: Wed, 22 Apr 2009 13:54:18 -0700
Subject: [llvm-commits] [llvm] r69574	-
	/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
In-Reply-To: <49EC9FCB.7040501@microchip.com>
References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu>
	<83B4B74F-3F9C-4A66-8447-40970738F0AD@apple.com>
	<49EC9FCB.7040501@microchip.com>
Message-ID: 


On Apr 20, 2009, at 9:16 AM, Sanjiv Gupta wrote:

> Dan Gohman wrote:
>> Hello,
>>
>> Are you planning to resubmit r58505?  It was reverted in r58547 with
>> a message indicating that it would be resubmitted.  That patch would
>> appear to make this r69574 unnecessary.
>>
>> Dan
>>
>>
> Right. Even after that this change will still hold good just in case  
> if
> a pointer size doesn't make valid index.

If Instcombine isn't using a valid index type for this optimization
for some target, it really should be fixed. Silently falling back to
not doing this may just be hiding problems.

>
> Chris had suggested that 58505 alone is not enough as the bc encoding
> uses 1 bit to encode i32/i64 for index types.
> He had suggested that we should be able to write i16 type indexes and
> should be able to get back them by the command seq below.
>  $ llvm-as < test.ll | llvm-dis | llvm-as | llvm-dis
>
> When I tried this with 58505, it worked.
> So the only additional thing is that we  probably need to do the  
> changes
> in the documentation.
>
> Let me know if this understanding is incorrect. Better you can get  
> me a
> test case.

I'm not very familiar with the bitcode encoding, but at a quick
glance it looks like a full type is stored with each operand.
If this just needs a documentation update, please do that and
re-apply 58505.

Thanks,

Dan



From lattner at apple.com  Wed Apr 22 17:17:18 2009
From: lattner at apple.com (Tanya Lattner)
Date: Wed, 22 Apr 2009 15:17:18 -0700
Subject: [llvm-commits] [llvm] r69693 -
	/llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp
In-Reply-To: <200904211829.n3LITjhE031349@zion.cs.uiuc.edu>
References: <200904211829.n3LITjhE031349@zion.cs.uiuc.edu>
Message-ID: <6F94ABBD-1C6A-4D1D-84A3-4BC3EB628797@apple.com>

Should you be committing to a tag?

-Tanya

On Apr 21, 2009, at 11:29 AM, Bill Wendling wrote:

> Author: void
> Date: Tue Apr 21 13:29:45 2009
> New Revision: 69693
>
> URL: http://llvm.org/viewvc/llvm-project?rev=69693&view=rev
> Log:
> --- Merging r69314 into '.':
> U    lib/ExecutionEngine/JIT/JIT.cpp
>
> Merge in this fix into llvmCore-2105.2.
>
> Modified:
>    llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp
>
> Modified: llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/ 
> JIT.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp?rev=69693&r1=69692&r2=69693&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp  
> (original)
> +++ llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp  
> Tue Apr 21 13:29:45 2009
> @@ -231,11 +231,9 @@
>   // The key is created on demand, and libgcc creates it the first  
> time an
>   // exception occurs. Since we need the key to register frames, we  
> create
>   // it now.
> -  if (!LOI) {
> -    LOI = (LibgccObjectInfo*)malloc(sizeof(struct LibgccObjectInfo));
> -    _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,
> -                                           LOI);
> -  }
> +  if (!LOI)
> +    LOI = (LibgccObjectInfo*)calloc(sizeof(struct  
> LibgccObjectInfo), 1);
> +  _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,  
> LOI);
>   InstallExceptionTableRegister(DarwinRegisterFrame);
> #else
>   InstallExceptionTableRegister(__register_frame);
>
>
> _______________________________________________
> 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/20090422/cf50a1ca/attachment.html 

From greened at obbligato.org  Wed Apr 22 17:17:51 2009
From: greened at obbligato.org (David Greene)
Date: Wed, 22 Apr 2009 22:17:51 -0000
Subject: [llvm-commits] [llvm] r69832 - in /llvm/trunk:
 docs/TableGenFundamentals.html test/TableGen/DefmInherit.td
 utils/TableGen/TGParser.cpp
Message-ID: <200904222217.n3MMHphs027898@zion.cs.uiuc.edu>

Author: greened
Date: Wed Apr 22 17:17:51 2009
New Revision: 69832

URL: http://llvm.org/viewvc/llvm-project?rev=69832&view=rev
Log:

Allow defm to inherit from multiple multiclasses.

Added:
    llvm/trunk/test/TableGen/DefmInherit.td
Modified:
    llvm/trunk/docs/TableGenFundamentals.html
    llvm/trunk/utils/TableGen/TGParser.cpp

Modified: llvm/trunk/docs/TableGenFundamentals.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGenFundamentals.html?rev=69832&r1=69831&r2=69832&view=diff

==============================================================================
--- llvm/trunk/docs/TableGenFundamentals.html (original)
+++ llvm/trunk/docs/TableGenFundamentals.html Wed Apr 22 17:17:51 2009
@@ -632,9 +632,10 @@
 
 

The name of the resultant definitions has the multidef fragment names appended to them, so this defines ADD_rr, ADD_ri, - SUB_rr, etc. Using a multiclass this way is exactly - equivalent to instantiating the classes multiple times yourself, - e.g. by writing:

+ SUB_rr, etc. A defm may inherit from multiple multiclasses, + instantiating definitions from each multiclass. Using a multiclass + this way is exactly equivalent to instantiating the classes multiple + times yourself, e.g. by writing:


Added: llvm/trunk/test/TableGen/DefmInherit.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/DefmInherit.td?rev=69832&view=auto

==============================================================================
--- llvm/trunk/test/TableGen/DefmInherit.td (added)
+++ llvm/trunk/test/TableGen/DefmInherit.td Wed Apr 22 17:17:51 2009
@@ -0,0 +1,32 @@
+// RUN: tblgen %s | grep {zing = 4} | count 4
+
+class C1 { 
+  int bar = A;
+  string thestr = B;
+  int zing;
+}
+
+def T : C1<4, "blah">;
+
+multiclass t {
+  def S1 : C1 {
+    int foo = 4;
+    let bar = 1;
+  }
+  def S2 : C1;
+}
+
+multiclass s {
+  def S3 : C1 {
+    int moo = 3;
+    let bar = 1;
+  }
+  def S4 : C1;
+}
+
+defm FOO : t<42>, s<24>;
+
+def T4 : C1<6, "foo">;
+
+let zing = 4 in
+  defm BAZ : t<3>, s<4>;

Modified: llvm/trunk/utils/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.cpp?rev=69832&r1=69831&r2=69832&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TGParser.cpp (original)
+++ llvm/trunk/utils/TableGen/TGParser.cpp Wed Apr 22 17:17:51 2009
@@ -1482,77 +1482,85 @@
 
   TGLoc SubClassLoc = Lex.getLoc();
   SubClassReference Ref = ParseSubClassReference(0, true);
-  if (Ref.Rec == 0) return true;
-  
-  if (Lex.getCode() != tgtok::semi)
-    return TokError("expected ';' at end of defm");
-  Lex.Lex();
-  
-  // To instantiate a multiclass, we need to first get the multiclass, then
-  // instantiate each def contained in the multiclass with the SubClassRef
-  // template parameters.
-  MultiClass *MC = MultiClasses[Ref.Rec->getName()];
-  assert(MC && "Didn't lookup multiclass correctly?");
-  std::vector &TemplateVals = Ref.TemplateArgs;
-  
-  // Verify that the correct number of template arguments were specified.
-  const std::vector &TArgs = MC->Rec.getTemplateArgs();
-  if (TArgs.size() < TemplateVals.size())
-    return Error(SubClassLoc,
-                 "more template args specified than multiclass expects");
-  
-  // Loop over all the def's in the multiclass, instantiating each one.
-  for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) {
-    Record *DefProto = MC->DefPrototypes[i];
-    
-    // Add the suffix to the defm name to get the new name.
-    Record *CurRec = new Record(DefmPrefix + DefProto->getName(),DefmPrefixLoc);
-    
-    SubClassReference Ref;
-    Ref.RefLoc = DefmPrefixLoc;
-    Ref.Rec = DefProto;
-    AddSubClass(CurRec, Ref);
-    
-    // Loop over all of the template arguments, setting them to the specified
-    // value or leaving them as the default if necessary.
-    for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
-      if (i < TemplateVals.size()) { // A value is specified for this temp-arg?
-        // Set it now.
-        if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector(),
-                     TemplateVals[i]))
-          return true;
-        
-        // Resolve it next.
-        CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
-        
-        // Now remove it.
-        CurRec->removeValue(TArgs[i]);
-        
-      } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
-        return Error(SubClassLoc, "value not specified for template argument #"+
-                     utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" +
-                     MC->Rec.getName() + "'");
+
+  while (1) {
+    if (Ref.Rec == 0) return true;
+
+    // To instantiate a multiclass, we need to first get the multiclass, then
+    // instantiate each def contained in the multiclass with the SubClassRef
+    // template parameters.
+    MultiClass *MC = MultiClasses[Ref.Rec->getName()];
+    assert(MC && "Didn't lookup multiclass correctly?");
+    std::vector &TemplateVals = Ref.TemplateArgs;   
+
+    // Verify that the correct number of template arguments were specified.
+    const std::vector &TArgs = MC->Rec.getTemplateArgs();
+    if (TArgs.size() < TemplateVals.size())
+      return Error(SubClassLoc,
+                   "more template args specified than multiclass expects");
+
+    // Loop over all the def's in the multiclass, instantiating each one.
+    for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) {
+      Record *DefProto = MC->DefPrototypes[i];
+
+      // Add the suffix to the defm name to get the new name.
+      Record *CurRec = new Record(DefmPrefix + DefProto->getName(), DefmPrefixLoc);
+
+      SubClassReference Ref;
+      Ref.RefLoc = DefmPrefixLoc;
+      Ref.Rec = DefProto;
+      AddSubClass(CurRec, Ref);
+
+      // Loop over all of the template arguments, setting them to the specified
+      // value or leaving them as the default if necessary.
+      for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+        if (i < TemplateVals.size()) { // A value is specified for this temp-arg?
+          // Set it now.
+          if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector(),
+                       TemplateVals[i]))
+            return true;
+
+          // Resolve it next.
+          CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
+
+          // Now remove it.
+          CurRec->removeValue(TArgs[i]);
+
+        } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
+          return Error(SubClassLoc, "value not specified for template argument #"+
+                       utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" +
+                       MC->Rec.getName() + "'");
+        }
       }
+
+      // If the mdef is inside a 'let' expression, add to each def.
+      for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
+        for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
+          if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
+                       LetStack[i][j].Bits, LetStack[i][j].Value)) {
+            Error(DefmPrefixLoc, "when instantiating this defm");
+            return true;
+          }
+
+      // Ensure redefinition doesn't happen.
+      if (Records.getDef(CurRec->getName()))
+        return Error(DefmPrefixLoc, "def '" + CurRec->getName() + 
+                     "' already defined, instantiating defm with subdef '" + 
+                     DefProto->getName() + "'");
+      Records.addDef(CurRec);
+      CurRec->resolveReferences();
     }
-    
-    // If the mdef is inside a 'let' expression, add to each def.
-    for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
-      for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
-        if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
-                     LetStack[i][j].Bits, LetStack[i][j].Value)) {
-          Error(DefmPrefixLoc, "when instantiating this defm");
-          return true;
-        }
-    
-    
-    // Ensure redefinition doesn't happen.
-    if (Records.getDef(CurRec->getName()))
-      return Error(DefmPrefixLoc, "def '" + CurRec->getName() + 
-                   "' already defined, instantiating defm with subdef '" + 
-                   DefProto->getName() + "'");
-    Records.addDef(CurRec);
-    CurRec->resolveReferences();
+
+    if (Lex.getCode() != tgtok::comma) break;
+    Lex.Lex(); // eat ','.
+
+    SubClassLoc = Lex.getLoc();
+    Ref = ParseSubClassReference(0, true);
   }
+
+  if (Lex.getCode() != tgtok::semi)
+    return TokError("expected ';' at end of defm");
+  Lex.Lex();
   
   return false;
 }




From isanbard at gmail.com  Wed Apr 22 17:39:35 2009
From: isanbard at gmail.com (Bill Wendling)
Date: Wed, 22 Apr 2009 15:39:35 -0700
Subject: [llvm-commits] [llvm] r69693 -
	/llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp
In-Reply-To: <6F94ABBD-1C6A-4D1D-84A3-4BC3EB628797@apple.com>
References: <200904211829.n3LITjhE031349@zion.cs.uiuc.edu>
	<6F94ABBD-1C6A-4D1D-84A3-4BC3EB628797@apple.com>
Message-ID: <16e5fdf90904221539q5fee0739l9b9df39740ee5c87@mail.gmail.com>

In this case, yes. :-) I copied 2105.2 from 2105.1 and then modified 2105.2.

-bw

On Wed, Apr 22, 2009 at 3:17 PM, Tanya Lattner  wrote:
> Should you be committing to a tag?
> -Tanya
> On Apr 21, 2009, at 11:29 AM, Bill Wendling wrote:
>
> Author: void
> Date: Tue Apr 21 13:29:45 2009
> New Revision: 69693
>
> URL: http://llvm.org/viewvc/llvm-project?rev=69693&view=rev
> Log:
> --- Merging r69314 into '.':
> U ???lib/ExecutionEngine/JIT/JIT.cpp
>
> Merge in this fix into llvmCore-2105.2.
>
> Modified:
> ???llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp
>
> Modified: llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp?rev=69693&r1=69692&r2=69693&view=diff
>
> ==============================================================================
> --- llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp
> (original)
> +++ llvm/tags/Apple/llvmCore-2105.2/lib/ExecutionEngine/JIT/JIT.cpp Tue Apr
> 21 13:29:45 2009
> @@ -231,11 +231,9 @@
> ??// The key is created on demand, and libgcc creates it the first time an
> ??// exception occurs. Since we need the key to register frames, we create
> ??// it now.
> - ?if (!LOI) {
> - ???LOI = (LibgccObjectInfo*)malloc(sizeof(struct LibgccObjectInfo));
> - ???_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,
> - ??????????????????????????????????????????LOI);
> - ?}
> + ?if (!LOI)
> + ???LOI = (LibgccObjectInfo*)calloc(sizeof(struct LibgccObjectInfo), 1);
> + ?_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, LOI);
> ??InstallExceptionTableRegister(DarwinRegisterFrame);
> #else
> ??InstallExceptionTableRegister(__register_frame);
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
> _______________________________________________
> 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  Wed Apr 22 17:45:37 2009
From: evan.cheng at apple.com (Evan Cheng)
Date: Wed, 22 Apr 2009 22:45:37 -0000
Subject: [llvm-commits] [llvm] r69836 - in /llvm/trunk:
 lib/Transforms/Scalar/IndVarSimplify.cpp
 test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll
Message-ID: <200904222245.n3MMjbMm028915@zion.cs.uiuc.edu>

Author: evancheng
Date: Wed Apr 22 17:45:37 2009
New Revision: 69836

URL: http://llvm.org/viewvc/llvm-project?rev=69836&view=rev
Log:
Avoid deferencing use_begin() if value does not have a use.

Added:
    llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=69836&r1=69835&r2=69836&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Wed Apr 22 17:45:37 2009
@@ -806,6 +806,7 @@
         // (RHS doesn't have to be constant.  There should be a better approach
         // than bottom-up pattern matching for this...)
         if (UInst && UInst->getOpcode()==Instruction::And &&
+            !UInst->use_empty() &&
             allUsesAreSameTyped(Instruction::ZExt, UInst) &&
             isa(UInst->getOperand(1))) {
           uint64_t newBitSize = LargestType->getPrimitiveSizeInBits();

Added: llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll?rev=69836&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll Wed Apr 22 17:45:37 2009
@@ -0,0 +1,17 @@
+; RUN: llvm-as < %s | opt -indvars
+
+define i32 @t() nounwind ssp {
+entry:
+	br label %bb32
+
+bb32:		; preds = %bb32, %entry
+	%mbPartIdx.0.reg2mem.0 = phi i8 [ %2, %bb32 ], [ 0, %entry ]		;  [#uses=3]
+	%0 = and i8 %mbPartIdx.0.reg2mem.0, 1		;  [#uses=0]
+	%1 = zext i8 %mbPartIdx.0.reg2mem.0 to i64		;  [#uses=0]
+	%2 = add i8 %mbPartIdx.0.reg2mem.0, 1		;  [#uses=2]
+	%3 = icmp ugt i8 %2, 3		;  [#uses=1]
+	br i1 %3, label %bb41, label %bb32
+
+bb41:		; preds = %bb32
+	ret i32 0
+}




From evan.cheng at apple.com  Wed Apr 22 18:09:17 2009
From: evan.cheng at apple.com (Evan Cheng)
Date: Wed, 22 Apr 2009 23:09:17 -0000
Subject: [llvm-commits] [llvm] r69842 -
	/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
Message-ID: <200904222309.n3MN9HYB029688@zion.cs.uiuc.edu>

Author: evancheng
Date: Wed Apr 22 18:09:16 2009
New Revision: 69842

URL: http://llvm.org/viewvc/llvm-project?rev=69842&view=rev
Log:
A few more places where the check of use_empty is needed.

Modified:
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=69842&r1=69841&r2=69842&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Wed Apr 22 18:09:16 2009
@@ -739,6 +739,7 @@
         // See if we can figure out sext(i+constant) doesn't wrap, so we can
         // use a larger add.  This is common in subscripting.
         if (UInst && UInst->getOpcode()==Instruction::Add &&
+            !UInst->use_empty() &&
             allUsesAreSameTyped(Instruction::SExt, UInst) &&
             isa(UInst->getOperand(1)) &&
             NoSignedWrap && LimitVal) {
@@ -771,6 +772,7 @@
         // Try for sext(i | constant).  This is safe as long as the
         // high bit of the constant is not set.
         if (UInst && UInst->getOpcode()==Instruction::Or &&
+            !UInst->use_empty() &&
             allUsesAreSameTyped(Instruction::SExt, UInst) && NoSignedWrap &&
             isa(UInst->getOperand(1))) {
           ConstantInt* RHS = dyn_cast(UInst->getOperand(1));
@@ -841,6 +843,7 @@
           ConstantInt* AddRHS = dyn_cast(UInst->getOperand(1));
           Instruction *UInst2 = dyn_cast(UInst->use_begin());
           if (UInst2 && UInst2->getOpcode() == Instruction::And &&
+              !UInst2->use_empty() &&
               allUsesAreSameTyped(Instruction::ZExt, UInst2) &&
               isa(UInst2->getOperand(1))) {
             ZExtInst* oldZext = dyn_cast(UInst2->use_begin());




From isanbard at gmail.com  Wed Apr 22 18:21:58 2009
From: isanbard at gmail.com (Bill Wendling)
Date: Wed, 22 Apr 2009 16:21:58 -0700
Subject: [llvm-commits] [llvm] r69785 -
	/llvm/trunk/include/llvm/ADT/SmallVector.h
In-Reply-To: <200904220716.n3M7Gtnk025567@zion.cs.uiuc.edu>
References: <200904220716.n3M7Gtnk025567@zion.cs.uiuc.edu>
Message-ID: <16e5fdf90904221621n21ce9781ta84e8487e3d67899@mail.gmail.com>

Testcase?

-bw

On Wed, Apr 22, 2009 at 12:16 AM, Owen Anderson  wrote:
> Author: resistor
> Date: Wed Apr 22 02:16:54 2009
> New Revision: 69785
>
> URL: http://llvm.org/viewvc/llvm-project?rev=69785&view=rev
> Log:
> Fix for PR3946, in which SmallVector could behave strangely in corner cases.
>
> Patch by Peter Johnson.
>
> 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=69785&r1=69784&r2=69785&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/SmallVector.h (original)
> +++ llvm/trunk/include/llvm/ADT/SmallVector.h Wed Apr 22 02:16:54 2009
> @@ -302,7 +302,7 @@
> ? ? ? append(End-NumToInsert, End);
>
> ? ? ? // Copy the existing elements that get replaced.
> - ? ? ?std::copy(I, OldEnd-NumToInsert, I+NumToInsert);
> + ? ? ?std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
>
> ? ? ? std::fill_n(I, NumToInsert, Elt);
> ? ? ? return I;
> @@ -351,7 +351,7 @@
> ? ? ? append(End-NumToInsert, End);
>
> ? ? ? // Copy the existing elements that get replaced.
> - ? ? ?std::copy(I, OldEnd-NumToInsert, I+NumToInsert);
> + ? ? ?std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
>
> ? ? ? std::copy(From, To, I);
> ? ? ? return I;
>
>
> _______________________________________________
> 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  Wed Apr 22 18:39:28 2009
From: evan.cheng at apple.com (Evan Cheng)
Date: Wed, 22 Apr 2009 23:39:28 -0000
Subject: [llvm-commits] [llvm] r69844 - in /llvm/trunk:
 lib/Transforms/Scalar/IndVarSimplify.cpp
 test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll
Message-ID: <200904222339.n3MNdSnO030565@zion.cs.uiuc.edu>

Author: evancheng
Date: Wed Apr 22 18:39:28 2009
New Revision: 69844

URL: http://llvm.org/viewvc/llvm-project?rev=69844&view=rev
Log:
Make sure both operands have binary instructions have the same type.

Modified:
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=69844&r1=69843&r2=69844&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Wed Apr 22 18:39:28 2009
@@ -751,11 +751,14 @@
             // We've determined this is (i+constant) and it won't overflow.
             if (isa(UInst->use_begin())) {
               SExtInst* oldSext = dyn_cast(UInst->use_begin());
+              uint64_t truncSize = oldSext->getType()->getPrimitiveSizeInBits();
               Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
                                                 L, oldSext->getType(), Rewriter,
                                                 InsertPt);
-              APInt APcopy = APInt(AddRHS->getValue());
-              ConstantInt* newAddRHS =ConstantInt::get(APcopy.sext(newBitSize));
+              APInt APnewAddRHS = APInt(AddRHS->getValue()).sext(newBitSize);
+              if (newBitSize > truncSize)
+                APnewAddRHS = APnewAddRHS.trunc(truncSize);
+              ConstantInt* newAddRHS =ConstantInt::get(APnewAddRHS);
               Value *NewAdd = 
                     BinaryOperator::CreateAdd(TruncIndVar, newAddRHS,
                                               UInst->getName()+".nosex", UInst);
@@ -779,18 +782,21 @@
           if (!RHS->getValue().isNegative()) {
             uint64_t newBitSize = LargestType->getPrimitiveSizeInBits();
             SExtInst* oldSext = dyn_cast(UInst->use_begin());
+            uint64_t truncSize = oldSext->getType()->getPrimitiveSizeInBits();
             Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
                                               L, oldSext->getType(), Rewriter,
                                               InsertPt);
-            APInt APcopy = APInt(RHS->getValue());
-            ConstantInt* newRHS =ConstantInt::get(APcopy.sext(newBitSize));
-            Value *NewAdd = 
-                  BinaryOperator::CreateOr(TruncIndVar, newRHS,
+            APInt APnewOrRHS = APInt(RHS->getValue()).sext(newBitSize);
+            if (newBitSize > truncSize)
+              APnewOrRHS = APnewOrRHS.trunc(truncSize);
+            ConstantInt* newOrRHS =ConstantInt::get(APnewOrRHS);
+            Value *NewOr = 
+                  BinaryOperator::CreateOr(TruncIndVar, newOrRHS,
                                             UInst->getName()+".nosex", UInst);
             for (Value::use_iterator UI2 = UInst->use_begin(), 
                   UE2 = UInst->use_end(); UI2 != UE2; ++UI2) {
               Instruction *II = dyn_cast(UI2);
-              II->replaceAllUsesWith(NewAdd);
+              II->replaceAllUsesWith(NewOr);
               DeadInsts.insert(II);
             }
             DeadInsts.insert(UInst);
@@ -814,10 +820,13 @@
           uint64_t newBitSize = LargestType->getPrimitiveSizeInBits();
           ConstantInt* AndRHS = dyn_cast(UInst->getOperand(1));
           ZExtInst* oldZext = dyn_cast(UInst->use_begin());
+          uint64_t truncSize = oldZext->getType()->getPrimitiveSizeInBits();
           Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
                                   L, oldZext->getType(), Rewriter, InsertPt);
-          APInt APcopy = APInt(AndRHS->getValue());
-          ConstantInt* newAndRHS = ConstantInt::get(APcopy.zext(newBitSize));
+          APInt APnewAndRHS = APInt(AndRHS->getValue()).zext(newBitSize);
+          if (newBitSize > truncSize)
+            APnewAndRHS = APnewAndRHS.trunc(truncSize);
+          ConstantInt* newAndRHS = ConstantInt::get(APnewAndRHS);
           Value *NewAnd = 
                 BinaryOperator::CreateAnd(TruncIndVar, newAndRHS,
                                           UInst->getName()+".nozex", UInst);
@@ -847,11 +856,14 @@
               allUsesAreSameTyped(Instruction::ZExt, UInst2) &&
               isa(UInst2->getOperand(1))) {
             ZExtInst* oldZext = dyn_cast(UInst2->use_begin());
+            uint64_t truncSize = oldZext->getType()->getPrimitiveSizeInBits();
             Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
                                     L, oldZext->getType(), Rewriter, InsertPt);
             ConstantInt* AndRHS = dyn_cast(UInst2->getOperand(1));
-            APInt APcopy = APInt(AddRHS->getValue());
-            ConstantInt* newAddRHS = ConstantInt::get(APcopy.zext(newBitSize));
+            APInt APnewAddRHS = APInt(AddRHS->getValue()).zext(newBitSize);
+            if (newBitSize > truncSize)
+              APnewAddRHS = APnewAddRHS.trunc(truncSize);
+            ConstantInt* newAddRHS = ConstantInt::get(APnewAddRHS);
             Value *NewAdd = ((UInst->getOpcode()==Instruction::Add) ?
                   BinaryOperator::CreateAdd(TruncIndVar, newAddRHS,
                                             UInst->getName()+".nozex", UInst2) :

Modified: llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll?rev=69844&r1=69843&r2=69844&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll Wed Apr 22 18:39:28 2009
@@ -1,6 +1,7 @@
 ; RUN: llvm-as < %s | opt -indvars
+; rdar://6817574
 
-define i32 @t() nounwind ssp {
+define i32 @t1() nounwind ssp {
 entry:
 	br label %bb32
 
@@ -15,3 +16,20 @@
 bb41:		; preds = %bb32
 	ret i32 0
 }
+
+define i32 @t2() nounwind ssp {
+entry:
+	br label %bb116
+
+bb116:		; preds = %bb116, %entry
+	%mbPartIdx.1.reg2mem.0 = phi i8 [ %3, %bb116 ], [ 0, %entry ]		;  [#uses=3]
+	%0 = and i8 %mbPartIdx.1.reg2mem.0, 1		;  [#uses=1]
+	%1 = zext i8 %mbPartIdx.1.reg2mem.0 to i64		;  [#uses=0]
+	%2 = zext i8 %0 to i32		;  [#uses=0]
+	%3 = add i8 %mbPartIdx.1.reg2mem.0, 1		;  [#uses=2]
+	%4 = icmp ugt i8 %3, 3		;  [#uses=1]
+	br i1 %4, label %bb131, label %bb116
+
+bb131:		; preds = %bb116
+	unreachable
+}




From resistor at mac.com  Wed Apr 22 19:15:26 2009
From: resistor at mac.com (Owen Anderson)
Date: Thu, 23 Apr 2009 00:15:26 -0000
Subject: [llvm-commits] [llvm] r69846 -
	/llvm/trunk/unittests/ADT/SmallVectorTest.cpp
Message-ID: <200904230015.n3N0FQ4b031699@zion.cs.uiuc.edu>

Author: resistor
Date: Wed Apr 22 19:15:26 2009
New Revision: 69846

URL: http://llvm.org/viewvc/llvm-project?rev=69846&view=rev
Log:
Use the testcase from PR2791.

Modified:
    llvm/trunk/unittests/ADT/SmallVectorTest.cpp

Modified: llvm/trunk/unittests/ADT/SmallVectorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/SmallVectorTest.cpp?rev=69846&r1=69845&r2=69846&view=diff

==============================================================================
--- llvm/trunk/unittests/ADT/SmallVectorTest.cpp (original)
+++ llvm/trunk/unittests/ADT/SmallVectorTest.cpp Wed Apr 22 19:15:26 2009
@@ -340,9 +340,9 @@
 TEST_F(SmallVectorTest, InsertRepeatedTest) {
   SCOPED_TRACE("InsertRepeatedTest");
 
-  makeSequence(theVector, 1, 3);
-  theVector.insert(theVector.begin() + 1, 3, Constructable(77));
-  assertValuesInOrder(theVector, 6u, 1, 77, 77, 77, 2, 3);
+  makeSequence(theVector, 10, 15);
+  theVector.insert(theVector.begin() + 1, 2, Constructable(16));
+  assertValuesInOrder(theVector, 8u, 10, 16, 16, 11, 12, 13, 14, 15);
 }
 
 // Insert range.




From gohman at apple.com  Wed Apr 22 19:28:33 2009
From: gohman at apple.com (Dan Gohman)
Date: Thu, 23 Apr 2009 00:28:33 -0000
Subject: [llvm-commits] [llvm] r69847 - /llvm/trunk/test/Makefile
Message-ID: <200904230028.n3N0SY15032113@zion.cs.uiuc.edu>

Author: djg
Date: Wed Apr 22 19:28:31 2009
New Revision: 69847

URL: http://llvm.org/viewvc/llvm-project?rev=69847&view=rev
Log:
Add more ulimit limits, to catch more kinds of runaway behavior.

Modified:
    llvm/trunk/test/Makefile

Modified: llvm/trunk/test/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Makefile?rev=69847&r1=69846&r2=69847&view=diff

==============================================================================
--- llvm/trunk/test/Makefile (original)
+++ llvm/trunk/test/Makefile Wed Apr 22 19:28:31 2009
@@ -51,6 +51,7 @@
 ifneq ($(RUNTEST),)
 check-local:: site.exp
 	( ulimit -t 600 ; ulimit -d 512000 ; \
+	  ulimit -m 512000 ; ulimit -v 512000 ; \
 	  PATH="$(LLVMToolDir):$(LLVM_SRC_ROOT)/test/Scripts:$(PATH)" \
 	  $(RUNTEST) $(RUNTESTFLAGS) )
 else
@@ -74,6 +75,7 @@
 	  echo "source $(LLVM_SRC_ROOT)/test/lib/llvm.exp" ; \
 	  echo "RunLLVMTests $(TESTPATH)" ) | \
 	( ulimit -t 600 ; ulimit -d 512000 ; \
+	  ulimit -m 512000 ; ulimit -v 512000 ; \
 	  PATH="$(LLVMToolDir):$(LLVM_SRC_ROOT)/test/Scripts:$(PATH)" \
 	  $(TCLSH) )
 endif




From gohman at apple.com  Wed Apr 22 19:57:38 2009
From: gohman at apple.com (Dan Gohman)
Date: Thu, 23 Apr 2009 00:57:38 -0000
Subject: [llvm-commits] [llvm] r69848 -
	/llvm/trunk/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
Message-ID: <200904230057.n3N0vcGm000503@zion.cs.uiuc.edu>

Author: djg
Date: Wed Apr 22 19:57:37 2009
New Revision: 69848

URL: http://llvm.org/viewvc/llvm-project?rev=69848&view=rev
Log:
Add support for printing MO_ExternalSymbol operands in
memory operand tuples. This doesn't ever come up in normal
code however.

Modified:
    llvm/trunk/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp

Modified: llvm/trunk/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp?rev=69848&r1=69847&r2=69848&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp Wed Apr 22 19:57:37 2009
@@ -501,6 +501,7 @@
   }
   case MachineOperand::MO_ExternalSymbol: {
     bool isCallOp = Modifier && !strcmp(Modifier, "call");
+    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
     bool needCloseParen = false;
     std::string Name(TAI->getGlobalPrefix());
     Name += MO.getSymbolName();
@@ -511,7 +512,7 @@
       printSuffixedName(Name, "$stub");
       return;
     }
-    if (!isCallOp)
+    if (!isMemOp && !isCallOp)
       O << '$';
     else if (Name[0] == '$') {
       // The name begins with a dollar-sign. In order to avoid having it look
@@ -577,7 +578,8 @@
   bool NotRIPRel = IndexReg.getReg() || BaseReg.getReg();
   if (DispSpec.isGlobal() ||
       DispSpec.isCPI() ||
-      DispSpec.isJTI()) {
+      DispSpec.isJTI() ||
+      DispSpec.isSymbol()) {
     printOperand(MI, Op+3, "mem", NotRIPRel);
   } else {
     int DispVal = DispSpec.getImm();




From nicholas at mxc.ca  Wed Apr 22 21:52:43 2009
From: nicholas at mxc.ca (Nick Lewycky)
Date: Wed, 22 Apr 2009 19:52:43 -0700
Subject: [llvm-commits] [llvm] r69846
	-	/llvm/trunk/unittests/ADT/SmallVectorTest.cpp
In-Reply-To: <200904230015.n3N0FQ4b031699@zion.cs.uiuc.edu>
References: <200904230015.n3N0FQ4b031699@zion.cs.uiuc.edu>
Message-ID: <49EFD7FB.50508@mxc.ca>

Owen Anderson wrote:
> Author: resistor
> Date: Wed Apr 22 19:15:26 2009
> New Revision: 69846
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=69846&view=rev
> Log:
> Use the testcase from PR2791.

Have you got wrong PR?

> 
> Modified:
>     llvm/trunk/unittests/ADT/SmallVectorTest.cpp
> 
> Modified: llvm/trunk/unittests/ADT/SmallVectorTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/SmallVectorTest.cpp?rev=69846&r1=69845&r2=69846&view=diff
> 
> ==============================================================================
> --- llvm/trunk/unittests/ADT/SmallVectorTest.cpp (original)
> +++ llvm/trunk/unittests/ADT/SmallVectorTest.cpp Wed Apr 22 19:15:26 2009
> @@ -340,9 +340,9 @@
>  TEST_F(SmallVectorTest, InsertRepeatedTest) {
>    SCOPED_TRACE("InsertRepeatedTest");
>  
> -  makeSequence(theVector, 1, 3);
> -  theVector.insert(theVector.begin() + 1, 3, Constructable(77));
> -  assertValuesInOrder(theVector, 6u, 1, 77, 77, 77, 2, 3);
> +  makeSequence(theVector, 10, 15);
> +  theVector.insert(theVector.begin() + 1, 2, Constructable(16));
> +  assertValuesInOrder(theVector, 8u, 10, 16, 16, 11, 12, 13, 14, 15);
>  }
>  
>  // Insert range.
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 



From resistor at mac.com  Wed Apr 22 22:54:03 2009
From: resistor at mac.com (Owen Anderson)
Date: Wed, 22 Apr 2009 20:54:03 -0700
Subject: [llvm-commits] [llvm] r69846	-
 /llvm/trunk/unittests/ADT/SmallVectorTest.cpp
In-Reply-To: <49EFD7FB.50508@mxc.ca>
References: <200904230015.n3N0FQ4b031699@zion.cs.uiuc.edu>
	<49EFD7FB.50508@mxc.ca>
Message-ID: <80D6C57B-5604-4D13-BE76-0C4796D70C4D@mac.com>

Yes.  I meant 3946.

--Owen

On Apr 22, 2009, at 7:52 PM, Nick Lewycky wrote:

> Owen Anderson wrote:
>> Author: resistor
>> Date: Wed Apr 22 19:15:26 2009
>> New Revision: 69846
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=69846&view=rev
>> Log:
>> Use the testcase from PR2791.
>
> Have you got wrong PR?
>
>>
>> Modified:
>>    llvm/trunk/unittests/ADT/SmallVectorTest.cpp
>>
>> Modified: llvm/trunk/unittests/ADT/SmallVectorTest.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/SmallVectorTest.cpp?rev=69846&r1=69845&r2=69846&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/unittests/ADT/SmallVectorTest.cpp (original)
>> +++ llvm/trunk/unittests/ADT/SmallVectorTest.cpp Wed Apr 22  
>> 19:15:26 2009
>> @@ -340,9 +340,9 @@
>> TEST_F(SmallVectorTest, InsertRepeatedTest) {
>>   SCOPED_TRACE("InsertRepeatedTest");
>>
>> -  makeSequence(theVector, 1, 3);
>> -  theVector.insert(theVector.begin() + 1, 3, Constructable(77));
>> -  assertValuesInOrder(theVector, 6u, 1, 77, 77, 77, 2, 3);
>> +  makeSequence(theVector, 10, 15);
>> +  theVector.insert(theVector.begin() + 1, 2, Constructable(16));
>> +  assertValuesInOrder(theVector, 8u, 10, 16, 16, 11, 12, 13, 14,  
>> 15);
>> }
>>
>> // Insert range.
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



From resistor at mac.com  Wed Apr 22 23:14:04 2009
From: resistor at mac.com (Owen Anderson)
Date: Thu, 23 Apr 2009 04:14:04 -0000
Subject: [llvm-commits] [llvm] r69862 -
	/llvm/trunk/test/Transforms/LoopStrengthReduce/pr3086.ll
Message-ID: <200904230414.n3N4E4Hf006705@zion.cs.uiuc.edu>

Author: resistor
Date: Wed Apr 22 23:14:03 2009
New Revision: 69862

URL: http://llvm.org/viewvc/llvm-project?rev=69862&view=rev
Log:
Add testcase from PR3086.

Added:
    llvm/trunk/test/Transforms/LoopStrengthReduce/pr3086.ll

Added: llvm/trunk/test/Transforms/LoopStrengthReduce/pr3086.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/pr3086.ll?rev=69862&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LoopStrengthReduce/pr3086.ll (added)
+++ llvm/trunk/test/Transforms/LoopStrengthReduce/pr3086.ll Wed Apr 22 23:14:03 2009
@@ -0,0 +1,28 @@
+; RUN: llvm-as < %s | opt -loop-reduce -disable-output
+; PR 3086
+
+	%struct.Cls = type { i32, i8, [2 x %struct.Cls*], [2 x %struct.Lit*] }
+	%struct.Lit = type { i8 }
+
+define fastcc i64 @collect_clauses() nounwind {
+entry:
+	br label %bb11
+
+bb5:		; preds = %bb9
+	%0 = load %struct.Lit** %storemerge, align 8		; <%struct.Lit*> [#uses=0]
+	%indvar.next8 = add i64 %storemerge.rec, 1		;  [#uses=1]
+	br label %bb9
+
+bb9:		; preds = %bb22, %bb5
+	%storemerge.rec = phi i64 [ %indvar.next8, %bb5 ], [ 0, %bb22 ]		;  [#uses=2]
+	%storemerge = getelementptr %struct.Lit** null, i64 %storemerge.rec		; <%struct.Lit**> [#uses=2]
+	%1 = icmp ugt %struct.Lit** null, %storemerge		;  [#uses=1]
+	br i1 %1, label %bb5, label %bb22
+
+bb11:		; preds = %bb22, %entry
+	%2 = load %struct.Cls** null, align 8		; <%struct.Cls*> [#uses=0]
+	br label %bb22
+
+bb22:		; preds = %bb11, %bb9
+	br i1 false, label %bb11, label %bb9
+}




From resistor at mac.com  Wed Apr 22 23:21:14 2009
From: resistor at mac.com (Owen Anderson)
Date: Thu, 23 Apr 2009 04:21:14 -0000
Subject: [llvm-commits] [llvm] r69863 -
	/llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll
Message-ID: <200904230421.n3N4LFUN006997@zion.cs.uiuc.edu>

Author: resistor
Date: Wed Apr 22 23:21:14 2009
New Revision: 69863

URL: http://llvm.org/viewvc/llvm-project?rev=69863&view=rev
Log:
Testcase for PR3085.

Added:
    llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll

Added: llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll?rev=69863&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll (added)
+++ llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll Wed Apr 22 23:21:14 2009
@@ -0,0 +1,1945 @@
+; RUN: llvm-as < %s | opt -disable-output -loop-extract-single -loop-rotate
+-loop-reduce -argpromotion
+; PR 3085
+
+	%struct.Lit = type { i8 }
+
+define fastcc %struct.Lit* @import_lit(i32 %lit) nounwind {
+entry:
+	br i1 false, label %bb, label %bb1
+
+bb:		; preds = %entry
+	unreachable
+
+bb1:		; preds = %entry
+	br label %bb3
+
+bb2:		; preds = %bb3
+	br label %bb3
+
+bb3:		; preds = %bb2, %bb1
+	br i1 false, label %bb2, label %bb6
+
+bb6:		; preds = %bb3
+	br i1 false, label %bb.i.i, label %bb1.i.i
+
+bb.i.i:		; preds = %bb6
+	br label %int2lit.exit
+
+bb1.i.i:		; preds = %bb6
+	br label %int2lit.exit
+
+int2lit.exit:		; preds = %bb1.i.i, %bb.i.i
+	ret %struct.Lit* null
+}
+
+define fastcc i32 @picosat_main(i32 %argc, i8** %argv) nounwind {
+entry:
+	br i1 false, label %bb.i, label %picosat_time_stamp.exit
+
+bb.i:		; preds = %entry
+	br label %picosat_time_stamp.exit
+
+picosat_time_stamp.exit:		; preds = %bb.i, %entry
+	br label %bb108
+
+bb:		; preds = %bb108
+	br i1 false, label %bb1, label %bb2
+
+bb1:		; preds = %bb
+	br label %bb106
+
+bb2:		; preds = %bb
+	br i1 false, label %bb3, label %bb4
+
+bb3:		; preds = %bb2
+	br label %bb106
+
+bb4:		; preds = %bb2
+	br i1 false, label %bb5, label %bb6
+
+bb5:		; preds = %bb4
+	br label %bb106
+
+bb6:		; preds = %bb4
+	br i1 false, label %bb7, label %bb8
+
+bb7:		; preds = %bb6
+	br label %bb106
+
+bb8:		; preds = %bb6
+	br i1 false, label %bb106, label %bb10
+
+bb10:		; preds = %bb8
+	br i1 false, label %bb106, label %bb12
+
+bb12:		; preds = %bb10
+	br i1 false, label %bb106, label %bb14
+
+bb14:		; preds = %bb12
+	br i1 false, label %bb15, label %bb19
+
+bb15:		; preds = %bb14
+	br i1 false, label %bb16, label %bb17
+
+bb16:		; preds = %bb15
+	br label %bb106
+
+bb17:		; preds = %bb15
+	br label %bb106
+
+bb19:		; preds = %bb14
+	br i1 false, label %bb20, label %bb28
+
+bb20:		; preds = %bb19
+	br i1 false, label %bb21, label %bb22
+
+bb21:		; preds = %bb20
+	br label %bb106
+
+bb22:		; preds = %bb20
+	br i1 false, label %bb106, label %bb24
+
+bb24:		; preds = %bb22
+	br i1 false, label %bb106, label %bb26
+
+bb26:		; preds = %bb24
+	br label %bb106
+
+bb28:		; preds = %bb19
+	br i1 false, label %bb29, label %bb35
+
+bb29:		; preds = %bb28
+	br i1 false, label %bb30, label %bb31
+
+bb30:		; preds = %bb29
+	br label %bb106
+
+bb31:		; preds = %bb29
+	br i1 false, label %bb32, label %bb33
+
+bb32:		; preds = %bb31
+	br label %bb106
+
+bb33:		; preds = %bb31
+	br label %bb106
+
+bb35:		; preds = %bb28
+	br i1 false, label %bb36, label %bb40
+
+bb36:		; preds = %bb35
+	br i1 false, label %bb37, label %bb38
+
+bb37:		; preds = %bb36
+	br label %bb106
+
+bb38:		; preds = %bb36
+	br label %bb106
+
+bb40:		; preds = %bb35
+	br i1 false, label %bb41, label %bb49
+
+bb41:		; preds = %bb40
+	br i1 false, label %bb43, label %bb42
+
+bb42:		; preds = %bb41
+	br label %bb106
+
+bb43:		; preds = %bb41
+	br i1 false, label %bb44, label %bb45
+
+bb44:		; preds = %bb43
+	br label %bb106
+
+bb45:		; preds = %bb43
+	br i1 false, label %bb46, label %bb47
+
+bb46:		; preds = %bb45
+	br label %bb106
+
+bb47:		; preds = %bb45
+	br label %bb106
+
+bb49:		; preds = %bb40
+	br i1 false, label %bb50, label %bb56
+
+bb50:		; preds = %bb49
+	br i1 false, label %bb52, label %bb51
+
+bb51:		; preds = %bb50
+	br label %bb106
+
+bb52:		; preds = %bb50
+	br i1 false, label %bb53, label %bb54
+
+bb53:		; preds = %bb52
+	br label %bb106
+
+bb54:		; preds = %bb52
+	br label %bb106
+
+bb56:		; preds = %bb49
+	br i1 false, label %bb57, label %bb63
+
+bb57:		; preds = %bb56
+	br i1 false, label %bb59, label %bb58
+
+bb58:		; preds = %bb57
+	br label %bb106
+
+bb59:		; preds = %bb57
+	br i1 false, label %bb60, label %bb61
+
+bb60:		; preds = %bb59
+	br label %bb106
+
+bb61:		; preds = %bb59
+	br label %bb106
+
+bb63:		; preds = %bb56
+	br i1 false, label %bb64, label %bb70
+
+bb64:		; preds = %bb63
+	br i1 false, label %bb66, label %bb65
+
+bb65:		; preds = %bb64
+	br label %bb106
+
+bb66:		; preds = %bb64
+	br i1 false, label %bb67, label %bb68
+
+bb67:		; preds = %bb66
+	br label %bb106
+
+bb68:		; preds = %bb66
+	br label %bb106
+
+bb70:		; preds = %bb63
+	br i1 false, label %bb71, label %bb79
+
+bb71:		; preds = %bb70
+	br i1 false, label %bb73, label %bb72
+
+bb72:		; preds = %bb71
+	br label %bb106
+
+bb73:		; preds = %bb71
+	br i1 false, label %bb74, label %bb75
+
+bb74:		; preds = %bb73
+	br label %bb106
+
+bb75:		; preds = %bb73
+	br i1 false, label %bb76, label %bb77
+
+bb76:		; preds = %bb75
+	br label %bb106
+
+bb77:		; preds = %bb75
+	br label %bb106
+
+bb79:		; preds = %bb70
+	br i1 false, label %bb80, label %bb86
+
+bb80:		; preds = %bb79
+	br i1 false, label %bb82, label %bb81
+
+bb81:		; preds = %bb80
+	br label %bb106
+
+bb82:		; preds = %bb80
+	br i1 false, label %bb83, label %bb84
+
+bb83:		; preds = %bb82
+	br label %bb106
+
+bb84:		; preds = %bb82
+	br label %bb106
+
+bb86:		; preds = %bb79
+	br i1 false, label %bb87, label %bb93
+
+bb87:		; preds = %bb86
+	br i1 false, label %bb89, label %bb88
+
+bb88:		; preds = %bb87
+	br label %bb106
+
+bb89:		; preds = %bb87
+	br i1 false, label %bb90, label %bb91
+
+bb90:		; preds = %bb89
+	br label %bb106
+
+bb91:		; preds = %bb89
+	br label %bb106
+
+bb93:		; preds = %bb86
+	br i1 false, label %bb94, label %bb95
+
+bb94:		; preds = %bb93
+	br label %bb106
+
+bb95:		; preds = %bb93
+	br i1 false, label %bb98, label %bb97
+
+bb97:		; preds = %bb95
+	br label %bb106
+
+bb98:		; preds = %bb95
+	br i1 false, label %bb103, label %bb1.i24
+
+bb1.i24:		; preds = %bb98
+	br i1 false, label %bb99, label %bb103
+
+bb99:		; preds = %bb1.i24
+	br i1 false, label %bb101, label %bb100
+
+bb100:		; preds = %bb99
+	br label %bb102
+
+bb101:		; preds = %bb99
+	br label %bb102
+
+bb102:		; preds = %bb101, %bb100
+	br label %bb106
+
+bb103:		; preds = %bb1.i24, %bb98
+	br i1 false, label %bb104, label %bb105
+
+bb104:		; preds = %bb103
+	br label %bb106
+
+bb105:		; preds = %bb103
+	br label %bb106
+
+bb106:		; preds = %bb105, %bb104, %bb102, %bb97, %bb94, %bb91, %bb90, %bb88, %bb84, %bb83, %bb81, %bb77, %bb76, %bb74, %bb72, %bb68, %bb67, %bb65, %bb61, %bb60, %bb58, %bb54, %bb53, %bb51, %bb47, %bb46, %bb44, %bb42, %bb38, %bb37, %bb33, %bb32, %bb30, %bb26, %bb24, %bb22, %bb21, %bb17, %bb16, %bb12, %bb10, %bb8, %bb7, %bb5, %bb3, %bb1
+	br i1 false, label %bb108, label %bb110
+
+bb108:		; preds = %bb106, %picosat_time_stamp.exit
+	br i1 false, label %bb, label %bb110
+
+bb110:		; preds = %bb108, %bb106
+	br i1 false, label %bb112, label %bb171
+
+bb112:		; preds = %bb110
+	br i1 false, label %bb114, label %bb113
+
+bb113:		; preds = %bb112
+	br label %bb114
+
+bb114:		; preds = %bb113, %bb112
+	br i1 false, label %bb.i.i35, label %bb1.i.i36
+
+bb.i.i35:		; preds = %bb114
+	unreachable
+
+bb1.i.i36:		; preds = %bb114
+	br i1 false, label %bb5.i.i.i41, label %bb6.i.i.i42
+
+bb5.i.i.i41:		; preds = %bb1.i.i36
+	unreachable
+
+bb6.i.i.i42:		; preds = %bb1.i.i36
+	br i1 false, label %bb7.i.i.i43, label %bb8.i.i.i44
+
+bb7.i.i.i43:		; preds = %bb6.i.i.i42
+	br label %bb8.i.i.i44
+
+bb8.i.i.i44:		; preds = %bb7.i.i.i43, %bb6.i.i.i42
+	br i1 false, label %picosat_init.exit, label %bb14.i.i
+
+bb14.i.i:		; preds = %bb8.i.i.i44
+	br label %picosat_init.exit
+
+picosat_init.exit:		; preds = %bb14.i.i, %bb8.i.i.i44
+	br i1 false, label %bb116, label %bb115
+
+bb115:		; preds = %picosat_init.exit
+	br label %bb116
+
+bb116:		; preds = %bb115, %picosat_init.exit
+	br i1 false, label %bb119, label %bb118
+
+bb118:		; preds = %bb116
+	br label %bb119
+
+bb119:		; preds = %bb118, %bb116
+	br i1 false, label %bb121, label %bb120
+
+bb120:		; preds = %bb119
+	br label %bb121
+
+bb121:		; preds = %bb120, %bb119
+	br i1 false, label %bb126, label %bb122
+
+bb122:		; preds = %bb121
+	br label %bb126
+
+bb126:		; preds = %bb122, %bb121
+	br i1 false, label %bb128, label %bb127
+
+bb127:		; preds = %bb126
+	br label %bb128
+
+bb128:		; preds = %bb127, %bb126
+	br label %SKIP_COMMENTS.i
+
+SKIP_COMMENTS.i.loopexit:		; preds = %bb.i149, %bb.i149
+	br label %SKIP_COMMENTS.i.backedge
+
+SKIP_COMMENTS.i:		; preds = %SKIP_COMMENTS.i.backedge, %bb128
+	br i1 false, label %bb.i149.preheader, label %bb3.i152
+
+bb.i149.preheader:		; preds = %SKIP_COMMENTS.i
+	br label %bb.i149
+
+bb.i149:		; preds = %bb.i149, %bb.i149.preheader
+	switch i32 0, label %bb.i149 [
+		i32 -1, label %SKIP_COMMENTS.i.loopexit
+		i32 10, label %SKIP_COMMENTS.i.loopexit
+	]
+
+bb3.i152:		; preds = %SKIP_COMMENTS.i
+	br i1 false, label %bb4.i153, label %SKIP_COMMENTS.i.backedge
+
+SKIP_COMMENTS.i.backedge:		; preds = %bb3.i152, %SKIP_COMMENTS.i.loopexit
+	br label %SKIP_COMMENTS.i
+
+bb4.i153:		; preds = %bb3.i152
+	br i1 false, label %bb5.i154, label %bb129
+
+bb5.i154:		; preds = %bb4.i153
+	br i1 false, label %bb129, label %bb6.i155.preheader
+
+bb6.i155.preheader:		; preds = %bb5.i154
+	br label %bb6.i155
+
+bb6.i155:		; preds = %bb6.i155, %bb6.i155.preheader
+	br i1 false, label %bb7.i156, label %bb6.i155
+
+bb7.i156:		; preds = %bb6.i155
+	br i1 false, label %bb8.i157, label %bb129
+
+bb8.i157:		; preds = %bb7.i156
+	br i1 false, label %bb9.i158, label %bb129
+
+bb9.i158:		; preds = %bb8.i157
+	br i1 false, label %bb10.i159, label %bb129
+
+bb10.i159:		; preds = %bb9.i158
+	br i1 false, label %bb129, label %bb11.i160.preheader
+
+bb11.i160.preheader:		; preds = %bb10.i159
+	br label %bb11.i160
+
+bb11.i160:		; preds = %bb11.i160, %bb11.i160.preheader
+	br i1 false, label %bb12.i161, label %bb11.i160
+
+bb12.i161:		; preds = %bb11.i160
+	br i1 false, label %bb129, label %bb15.i165.preheader
+
+bb15.i165.preheader:		; preds = %bb12.i161
+	br label %bb15.i165
+
+bb14.i163:		; preds = %bb15.i165
+	br label %bb15.i165
+
+bb15.i165:		; preds = %bb14.i163, %bb15.i165.preheader
+	br i1 false, label %bb16.i166, label %bb14.i163
+
+bb16.i166:		; preds = %bb15.i165
+	br i1 false, label %bb129, label %bb17.i167.preheader
+
+bb17.i167.preheader:		; preds = %bb16.i166
+	br label %bb17.i167
+
+bb17.i167:		; preds = %bb17.i167, %bb17.i167.preheader
+	br i1 false, label %bb18.i168, label %bb17.i167
+
+bb18.i168:		; preds = %bb17.i167
+	br i1 false, label %bb129, label %bb21.i172.preheader
+
+bb21.i172.preheader:		; preds = %bb18.i168
+	br label %bb21.i172
+
+bb20.i170:		; preds = %bb21.i172
+	br label %bb21.i172
+
+bb21.i172:		; preds = %bb20.i170, %bb21.i172.preheader
+	br i1 false, label %bb22.i173, label %bb20.i170
+
+bb22.i173:		; preds = %bb21.i172
+	br i1 false, label %bb24.i175, label %bb129
+
+bb24.i175:		; preds = %bb22.i173
+	br i1 false, label %bb26.i180, label %bb25.i176
+
+bb25.i176:		; preds = %bb24.i175
+	br label %bb26.i180
+
+bb26.i180:		; preds = %bb25.i176, %bb24.i175
+	br i1 false, label %bb.i.i181, label %bb3.i.i184.preheader
+
+bb.i.i181:		; preds = %bb26.i180
+	br label %bb3.i.i184.preheader
+
+bb3.i.i184.preheader:		; preds = %bb.i.i181, %bb26.i180
+	br label %bb3.i.i184
+
+bb2.i.i183:		; preds = %bb3.i.i184
+	br label %bb3.i.i184
+
+bb3.i.i184:		; preds = %bb2.i.i183, %bb3.i.i184.preheader
+	br i1 false, label %bb2.i.i183, label %bb4.i.i185
+
+bb4.i.i185:		; preds = %bb3.i.i184
+	br i1 false, label %bb.i.i.i186, label %picosat_adjust.exit.i
+
+bb.i.i.i186:		; preds = %bb4.i.i185
+	br label %picosat_adjust.exit.i
+
+picosat_adjust.exit.i:		; preds = %bb.i.i.i186, %bb4.i.i185
+	br i1 false, label %bb28.i188, label %bb27.i187
+
+bb27.i187:		; preds = %picosat_adjust.exit.i
+	br label %bb28.i188
+
+bb28.i188:		; preds = %bb27.i187, %picosat_adjust.exit.i
+	br label %READ_LITERAL.i.outer
+
+READ_LITERAL.i.outer:		; preds = %READ_LITERAL.i.outer.backedge, %bb28.i188
+	br label %READ_LITERAL.i
+
+READ_LITERAL.i.loopexit:		; preds = %bb29.i189, %bb29.i189
+	br label %READ_LITERAL.i.backedge
+
+READ_LITERAL.i:		; preds = %READ_LITERAL.i.backedge, %READ_LITERAL.i.outer
+	switch i32 0, label %bb39.i199 [
+		i32 99, label %bb29.i189.preheader
+		i32 -1, label %bb33.i193
+	]
+
+bb29.i189.preheader:		; preds = %READ_LITERAL.i
+	br label %bb29.i189
+
+bb29.i189:		; preds = %bb29.i189, %bb29.i189.preheader
+	switch i32 0, label %bb29.i189 [
+		i32 -1, label %READ_LITERAL.i.loopexit
+		i32 10, label %READ_LITERAL.i.loopexit
+	]
+
+bb33.i193:		; preds = %READ_LITERAL.i
+	br i1 false, label %bb35.i195, label %parse.exit
+
+bb35.i195:		; preds = %bb33.i193
+	br i1 false, label %bb38.i198, label %parse.exit
+
+bb38.i198:		; preds = %bb35.i195
+	br label %parse.exit
+
+bb39.i199:		; preds = %READ_LITERAL.i
+	br i1 false, label %bb40.i200, label %READ_LITERAL.i.backedge
+
+READ_LITERAL.i.backedge:		; preds = %bb39.i199, %READ_LITERAL.i.loopexit
+	br label %READ_LITERAL.i
+
+bb40.i200:		; preds = %bb39.i199
+	br i1 false, label %bb41.i201, label %bb42.i202
+
+bb41.i201:		; preds = %bb40.i200
+	br label %bb42.i202
+
+bb42.i202:		; preds = %bb41.i201, %bb40.i200
+	br i1 false, label %parse.exit.loopexit, label %bb46.i.preheader
+
+bb46.i.preheader:		; preds = %bb42.i202
+	br label %bb46.i
+
+bb45.i:		; preds = %bb46.i
+	br label %bb46.i
+
+bb46.i:		; preds = %bb45.i, %bb46.i.preheader
+	br i1 false, label %bb47.i, label %bb45.i
+
+bb47.i:		; preds = %bb46.i
+	br i1 false, label %parse.exit.loopexit, label %bb50.i
+
+bb50.i:		; preds = %bb47.i
+	br i1 false, label %bb55.i, label %bb51.i
+
+bb51.i:		; preds = %bb50.i
+	br i1 false, label %parse.exit.loopexit, label %bb54.i
+
+bb54.i:		; preds = %bb51.i
+	br label %bb56.i
+
+bb55.i:		; preds = %bb50.i
+	br label %bb56.i
+
+bb56.i:		; preds = %bb55.i, %bb54.i
+	br i1 false, label %bb3.i11.i, label %bb.i8.i
+
+bb.i8.i:		; preds = %bb56.i
+	br i1 false, label %bb1.i9.i, label %bb3.i11.i
+
+bb1.i9.i:		; preds = %bb.i8.i
+	br i1 false, label %bb3.i11.i, label %bb2.i10.i
+
+bb2.i10.i:		; preds = %bb1.i9.i
+	unreachable
+
+bb3.i11.i:		; preds = %bb1.i9.i, %bb.i8.i, %bb56.i
+	br i1 false, label %bb7.i.i208, label %bb6.i.i207
+
+bb6.i.i207:		; preds = %bb3.i11.i
+	br label %READ_LITERAL.i.outer.backedge
+
+bb7.i.i208:		; preds = %bb3.i11.i
+	br i1 false, label %bb53.i.i.i.i.preheader, label %bb.i.i.i.i210.preheader
+
+bb.i.i.i.i210.preheader:		; preds = %bb7.i.i208
+	br label %bb.i.i.i.i210
+
+bb.i.i.i.i210:		; preds = %bb.i.i.i.i210.backedge, %bb.i.i.i.i210.preheader
+	br i1 false, label %bb17.i.i.i.i, label %bb18.i.i.i.i
+
+bb17.i.i.i.i:		; preds = %bb.i.i.i.i210
+	br label %bb18.i.i.i.i
+
+bb18.i.i.i.i:		; preds = %bb17.i.i.i.i, %bb.i.i.i.i210
+	br i1 false, label %bb19.i.i.i.i, label %bb20.i.i.i.i
+
+bb19.i.i.i.i:		; preds = %bb18.i.i.i.i
+	br label %bb20.i.i.i.i
+
+bb20.i.i.i.i:		; preds = %bb19.i.i.i.i, %bb18.i.i.i.i
+	br i1 false, label %bb21.i.i.i.i, label %bb22.i.i.i.i
+
+bb21.i.i.i.i:		; preds = %bb20.i.i.i.i
+	br label %bb22.i.i.i.i
+
+bb22.i.i.i.i:		; preds = %bb21.i.i.i.i, %bb20.i.i.i.i
+	br label %bb23.i.i.i.i.outer
+
+bb23.i.i.i.i.outer:		; preds = %bb28.i.i.i.i, %bb22.i.i.i.i
+	br label %bb23.i.i.i.i
+
+bb23.i.i.i.i:		; preds = %bb23.i.i.i.i, %bb23.i.i.i.i.outer
+	br i1 false, label %bb23.i.i.i.i, label %bb26.i.i.i.i.preheader
+
+bb26.i.i.i.i.preheader:		; preds = %bb23.i.i.i.i
+	br label %bb26.i.i.i.i
+
+bb26.i.i.i.i:		; preds = %bb26.i.i.i.i, %bb26.i.i.i.i.preheader
+	br i1 false, label %bb27.i.i.i.i, label %bb26.i.i.i.i
+
+bb27.i.i.i.i:		; preds = %bb26.i.i.i.i
+	br i1 false, label %bb28.i.i.i.i, label %bb29.i.i.i.i
+
+bb28.i.i.i.i:		; preds = %bb27.i.i.i.i
+	br label %bb23.i.i.i.i.outer
+
+bb29.i.i.i.i:		; preds = %bb27.i.i.i.i
+	br i1 false, label %bb33.i.i.i.i, label %bb44.i.i.i.i
+
+bb33.i.i.i.i:		; preds = %bb29.i.i.i.i
+	br i1 false, label %bb34.i.i.i.i, label %bb38.i.i.i.i
+
+bb34.i.i.i.i:		; preds = %bb33.i.i.i.i
+	br i1 false, label %bb37.i.i.i.i, label %bb35.i.i.i.i
+
+bb35.i.i.i.i:		; preds = %bb34.i.i.i.i
+	br label %bb37.i.i.i.i
+
+bb37.i.i.i.i:		; preds = %bb35.i.i.i.i, %bb34.i.i.i.i
+	br label %bb38.i.i.i.i
+
+bb38.i.i.i.i:		; preds = %bb37.i.i.i.i, %bb33.i.i.i.i
+	br i1 false, label %bb39.i.i.i.i, label %bb43.i.i.i.i
+
+bb39.i.i.i.i:		; preds = %bb38.i.i.i.i
+	br i1 false, label %bb42.i.i.i.i, label %bb40.i.i.i.i
+
+bb40.i.i.i.i:		; preds = %bb39.i.i.i.i
+	br label %bb42.i.i.i.i
+
+bb42.i.i.i.i:		; preds = %bb40.i.i.i.i, %bb39.i.i.i.i
+	br label %bb43.i.i.i.i
+
+bb43.i.i.i.i:		; preds = %bb42.i.i.i.i, %bb38.i.i.i.i
+	br label %bb.i.i.i.i210.backedge
+
+bb.i.i.i.i210.backedge:		; preds = %bb47.i.i.i.i, %bb44.i.i.i.i, %bb43.i.i.i.i
+	br label %bb.i.i.i.i210
+
+bb44.i.i.i.i:		; preds = %bb29.i.i.i.i
+	br i1 false, label %bb.i.i.i.i210.backedge, label %bb46.i.i.i.i
+
+bb46.i.i.i.i:		; preds = %bb44.i.i.i.i
+	br i1 false, label %bb47.i.i.i.i, label %bb53.i.i.i.i.preheader.loopexit
+
+bb53.i.i.i.i.preheader.loopexit:		; preds = %bb46.i.i.i.i
+	br label %bb53.i.i.i.i.preheader
+
+bb53.i.i.i.i.preheader:		; preds = %bb53.i.i.i.i.preheader.loopexit, %bb7.i.i208
+	br label %bb53.i.i.i.i
+
+bb47.i.i.i.i:		; preds = %bb46.i.i.i.i
+	br label %bb.i.i.i.i210.backedge
+
+bb50.i.i.i.i:		; preds = %bb53.i.i.i.i
+	br i1 false, label %bb51.i.i.i.i, label %bb52.i.i.i.i
+
+bb51.i.i.i.i:		; preds = %bb50.i.i.i.i
+	br label %bb52.i.i.i.i
+
+bb52.i.i.i.i:		; preds = %bb51.i.i.i.i, %bb50.i.i.i.i
+	br label %bb53.i.i.i.i
+
+bb53.i.i.i.i:		; preds = %bb52.i.i.i.i, %bb53.i.i.i.i.preheader
+	br i1 false, label %bb50.i.i.i.i, label %bb59.i.i.i.i.preheader
+
+bb59.i.i.i.i.preheader:		; preds = %bb53.i.i.i.i
+	br label %bb59.i.i.i.i
+
+bb55.i.i.i.i:		; preds = %bb59.i.i.i.i
+	br label %bb57.i.i.i.i
+
+bb56.i.i.i.i:		; preds = %bb57.i.i.i.i
+	br label %bb57.i.i.i.i
+
+bb57.i.i.i.i:		; preds = %bb56.i.i.i.i, %bb55.i.i.i.i
+	br i1 false, label %bb56.i.i.i.i, label %bb58.i.i.i.i
+
+bb58.i.i.i.i:		; preds = %bb57.i.i.i.i
+	br label %bb59.i.i.i.i
+
+bb59.i.i.i.i:		; preds = %bb58.i.i.i.i, %bb59.i.i.i.i.preheader
+	br i1 false, label %bb60.i.i.i.i, label %bb55.i.i.i.i
+
+bb60.i.i.i.i:		; preds = %bb59.i.i.i.i
+	br label %bb69.i.i.i.i
+
+bb61.i.i.i.i:		; preds = %bb69.i.i.i.i
+	br i1 false, label %bb68.i.i.i.i, label %bb62.i.i.i.i
+
+bb62.i.i.i.i:		; preds = %bb61.i.i.i.i
+	br i1 false, label %bb63.i.i.i.i, label %bb65.i.i.i.i
+
+bb63.i.i.i.i:		; preds = %bb62.i.i.i.i
+	br i1 false, label %bb.i.i12.i, label %bb65.i.i.i.i
+
+bb65.i.i.i.i:		; preds = %bb63.i.i.i.i, %bb62.i.i.i.i
+	br i1 false, label %bb.i.i12.i, label %bb67.i.i.i.i
+
+bb67.i.i.i.i:		; preds = %bb65.i.i.i.i
+	br label %bb68.i.i.i.i
+
+bb68.i.i.i.i:		; preds = %bb67.i.i.i.i, %bb61.i.i.i.i
+	br label %bb69.i.i.i.i
+
+bb69.i.i.i.i:		; preds = %bb68.i.i.i.i, %bb60.i.i.i.i
+	br i1 false, label %bb61.i.i.i.i, label %bb70.i.i.i.i
+
+bb70.i.i.i.i:		; preds = %bb69.i.i.i.i
+	br label %READ_LITERAL.i.outer.backedge
+
+bb.i.i12.i:		; preds = %bb65.i.i.i.i, %bb63.i.i.i.i
+	br i1 false, label %bb1.i.i.i213, label %bb5.i.i.i218
+
+bb1.i.i.i213:		; preds = %bb.i.i12.i
+	br i1 false, label %bb4.i.i.i217, label %bb2.i.i.i214
+
+bb2.i.i.i214:		; preds = %bb1.i.i.i213
+	br label %bb4.i.i.i217
+
+bb4.i.i.i217:		; preds = %bb2.i.i.i214, %bb1.i.i.i213
+	br label %bb5.i.i.i218
+
+bb5.i.i.i218:		; preds = %bb4.i.i.i217, %bb.i.i12.i
+	br label %READ_LITERAL.i.outer.backedge
+
+READ_LITERAL.i.outer.backedge:		; preds = %bb5.i.i.i218, %bb70.i.i.i.i, %bb6.i.i207
+	br label %READ_LITERAL.i.outer
+
+parse.exit.loopexit:		; preds = %bb51.i, %bb47.i, %bb42.i202
+	br label %parse.exit
+
+parse.exit:		; preds = %parse.exit.loopexit, %bb38.i198, %bb35.i195, %bb33.i193
+	br i1 false, label %bb130, label %bb129
+
+bb129:		; preds = %parse.exit, %bb22.i173, %bb18.i168, %bb16.i166, %bb12.i161, %bb10.i159, %bb9.i158, %bb8.i157, %bb7.i156, %bb5.i154, %bb4.i153
+	br label %bb170
+
+bb130:		; preds = %parse.exit
+	br i1 false, label %bb143, label %bb142.preheader
+
+bb142.preheader:		; preds = %bb130
+	br label %bb142
+
+bb132:		; preds = %bb142
+	br i1 false, label %bb137, label %bb133
+
+bb133:		; preds = %bb132
+	br i1 false, label %bb137, label %bb134
+
+bb134:		; preds = %bb133
+	br i1 false, label %bb137, label %bb135
+
+bb135:		; preds = %bb134
+	br i1 false, label %bb137, label %bb136
+
+bb136:		; preds = %bb135
+	br i1 false, label %bb137, label %bb138
+
+bb137:		; preds = %bb136, %bb135, %bb134, %bb133, %bb132
+	br label %bb141
+
+bb138:		; preds = %bb136
+	br i1 false, label %bb139, label %bb141
+
+bb139:		; preds = %bb138
+	br i1 false, label %bb2.i126, label %picosat_assume.exit
+
+bb2.i126:		; preds = %bb139
+	br i1 false, label %bb5.i130, label %bb3.i127
+
+bb3.i127:		; preds = %bb2.i126
+	br label %bb5.i130
+
+bb5.i130:		; preds = %bb3.i127, %bb2.i126
+	br label %picosat_assume.exit
+
+picosat_assume.exit:		; preds = %bb5.i130, %bb139
+	br i1 false, label %bb141, label %bb140
+
+bb140:		; preds = %picosat_assume.exit
+	br label %bb141
+
+bb141:		; preds = %bb140, %picosat_assume.exit, %bb138, %bb137
+	br label %bb142
+
+bb142:		; preds = %bb141, %bb142.preheader
+	br i1 false, label %bb132, label %bb143.loopexit
+
+bb143.loopexit:		; preds = %bb142
+	br label %bb143
+
+bb143:		; preds = %bb143.loopexit, %bb130
+	br i1 false, label %bb145, label %bb144
+
+bb144:		; preds = %bb143
+	br label %bb11.i
+
+bb5.i114:		; preds = %bb11.i
+	br label %bb11.i
+
+bb11.i:		; preds = %bb5.i114, %bb144
+	br i1 false, label %bb12.i, label %bb5.i114
+
+bb12.i:		; preds = %bb11.i
+	br i1 false, label %bb.i.i.i118, label %bb1.i.i.i119
+
+bb.i.i.i118:		; preds = %bb12.i
+	br label %int2lit.exit.i
+
+bb1.i.i.i119:		; preds = %bb12.i
+	br label %int2lit.exit.i
+
+int2lit.exit.i:		; preds = %bb1.i.i.i119, %bb.i.i.i118
+	br label %bb19.i
+
+bb13.i:		; preds = %bb19.i
+	br label %bb17.i
+
+bb14.i:		; preds = %bb17.i
+	br label %bb17.i
+
+bb17.i:		; preds = %bb14.i, %bb13.i
+	br i1 false, label %bb14.i, label %bb18.i
+
+bb18.i:		; preds = %bb17.i
+	br label %bb19.i
+
+bb19.i:		; preds = %bb18.i, %int2lit.exit.i
+	br i1 false, label %bb20.i, label %bb13.i
+
+bb20.i:		; preds = %bb19.i
+	br label %bb33.i
+
+bb24.i:		; preds = %bb33.i
+	br i1 false, label %bb29.i, label %bb25.i
+
+bb25.i:		; preds = %bb24.i
+	br label %bb27.i
+
+bb26.i:		; preds = %bb27.i
+	br label %bb27.i
+
+bb27.i:		; preds = %bb26.i, %bb25.i
+	br i1 false, label %bb26.i, label %bb28.i
+
+bb28.i:		; preds = %bb27.i
+	br label %bb29.i
+
+bb29.i:		; preds = %bb28.i, %bb24.i
+	br label %bb33.i
+
+bb33.i:		; preds = %bb29.i, %bb20.i
+	br i1 false, label %bb34.i, label %bb24.i
+
+bb34.i:		; preds = %bb33.i
+	br i1 false, label %bb.i.i58.i, label %bb1.i.i59.i
+
+bb.i.i58.i:		; preds = %bb34.i
+	br label %int2lit.exit63.i
+
+bb1.i.i59.i:		; preds = %bb34.i
+	br label %int2lit.exit63.i
+
+int2lit.exit63.i:		; preds = %bb1.i.i59.i, %bb.i.i58.i
+	br label %bb41.i
+
+bb35.i:		; preds = %bb41.i
+	br label %bb39.i
+
+bb36.i:		; preds = %bb39.i
+	br i1 false, label %bb38.i, label %bb37.i
+
+bb37.i:		; preds = %bb36.i
+	br label %bb38.i
+
+bb38.i:		; preds = %bb37.i, %bb36.i
+	br label %bb39.i
+
+bb39.i:		; preds = %bb38.i, %bb35.i
+	br i1 false, label %bb36.i, label %bb40.i
+
+bb40.i:		; preds = %bb39.i
+	br label %bb41.i
+
+bb41.i:		; preds = %bb40.i, %int2lit.exit63.i
+	br i1 false, label %bb42.i, label %bb35.i
+
+bb42.i:		; preds = %bb41.i
+	br label %bb44.i
+
+bb43.i:		; preds = %bb44.i
+	br label %bb44.i
+
+bb44.i:		; preds = %bb43.i, %bb42.i
+	br i1 false, label %bb43.i, label %picosat_print.exit
+
+picosat_print.exit:		; preds = %bb44.i
+	br label %bb167
+
+bb145:		; preds = %bb143
+	br i1 false, label %bb147, label %bb146
+
+bb146:		; preds = %bb145
+	br label %bb147
+
+bb147:		; preds = %bb146, %bb145
+	br i1 false, label %bb149, label %bb148
+
+bb148:		; preds = %bb147
+	br label %bb149
+
+bb149:		; preds = %bb148, %bb147
+	br i1 false, label %bb.i54, label %bb1.i55
+
+bb.i54:		; preds = %bb149
+	unreachable
+
+bb1.i55:		; preds = %bb149
+	br i1 false, label %bb.i.i56, label %bb1.i.i57
+
+bb.i.i56:		; preds = %bb1.i55
+	br label %bb1.i.i57
+
+bb1.i.i57:		; preds = %bb.i.i56, %bb1.i55
+	br i1 false, label %bb3.i.i59, label %bb2.i.i58
+
+bb2.i.i58:		; preds = %bb1.i.i57
+	br label %bb3.i.i59
+
+bb3.i.i59:		; preds = %bb2.i.i58, %bb1.i.i57
+	br i1 false, label %bb5.i.i61, label %sat.exit.i
+
+bb5.i.i61:		; preds = %bb3.i.i59
+	br i1 false, label %bb6.i.i65, label %bb1.i.i.i63
+
+bb1.i.i.i63:		; preds = %bb5.i.i61
+	br i1 false, label %sat.exit.i, label %bb6.i.i65
+
+bb6.i.i65:		; preds = %bb1.i.i.i63, %bb5.i.i61
+	br i1 false, label %bb8.i.i67, label %bb7.i.i66
+
+bb7.i.i66:		; preds = %bb6.i.i65
+	br label %bb8.i.i67
+
+bb8.i.i67:		; preds = %bb7.i.i66, %bb6.i.i65
+	br i1 false, label %bb10.i.i69, label %sat.exit.i
+
+bb10.i.i69:		; preds = %bb8.i.i67
+	br i1 false, label %bb11.i.i70, label %bb1.i61.i.i
+
+bb1.i61.i.i:		; preds = %bb10.i.i69
+	br i1 false, label %sat.exit.i, label %bb11.i.i70
+
+bb11.i.i70:		; preds = %bb1.i61.i.i, %bb10.i.i69
+	br label %bb13.i.i71.outer
+
+bb13.i.i71.outer:		; preds = %bb42.i.i, %bb11.i.i70
+	br label %bb13.i.i71
+
+bb13.i.i71:		; preds = %bb13.i.i71.backedge, %bb13.i.i71.outer
+	br i1 false, label %bb14.i.i72, label %bb15.i.i73
+
+bb14.i.i72:		; preds = %bb13.i.i71
+	br label %bb15.i.i73
+
+bb15.i.i73:		; preds = %bb14.i.i72, %bb13.i.i71
+	br i1 false, label %bb19.i.i, label %bb16.i.i
+
+bb16.i.i:		; preds = %bb15.i.i73
+	br i1 false, label %bb.i.i79.i.i, label %incincs.exit.i.i
+
+bb.i.i79.i.i:		; preds = %bb16.i.i
+	br label %bb4.i.i.i85.i.i
+
+bb.i.i.i80.i.i:		; preds = %bb4.i.i.i85.i.i
+	br i1 false, label %bb3.i.i.i83.i.i, label %bb1.i.i.i81.i.i
+
+bb1.i.i.i81.i.i:		; preds = %bb.i.i.i80.i.i
+	br i1 false, label %bb2.i.i.i82.i.i, label %bb3.i.i.i83.i.i
+
+bb2.i.i.i82.i.i:		; preds = %bb1.i.i.i81.i.i
+	br label %bb3.i.i.i83.i.i
+
+bb3.i.i.i83.i.i:		; preds = %bb2.i.i.i82.i.i, %bb1.i.i.i81.i.i, %bb.i.i.i80.i.i
+	br label %bb4.i.i.i85.i.i
+
+bb4.i.i.i85.i.i:		; preds = %bb3.i.i.i83.i.i, %bb.i.i79.i.i
+	br i1 false, label %crescore.exit.i.i.i.i, label %bb.i.i.i80.i.i
+
+crescore.exit.i.i.i.i:		; preds = %bb4.i.i.i85.i.i
+	br label %incincs.exit.i.i
+
+incincs.exit.i.i:		; preds = %crescore.exit.i.i.i.i, %bb16.i.i
+	br i1 false, label %bb13.i.i71.backedge, label %sat.exit.i.loopexit.loopexit
+
+bb13.i.i71.backedge:		; preds = %bb1.i55.i.i, %bb28.i.i, %incincs.exit.i.i
+	br label %bb13.i.i71
+
+bb19.i.i:		; preds = %bb15.i.i73
+	br i1 false, label %bb20.i.i, label %bb1.i68.i.i
+
+bb1.i68.i.i:		; preds = %bb19.i.i
+	br i1 false, label %sat.exit.i.loopexit.loopexit, label %bb20.i.i
+
+bb20.i.i:		; preds = %bb1.i68.i.i, %bb19.i.i
+	br i1 false, label %bb24.i.i, label %bb21.i.i
+
+bb21.i.i:		; preds = %bb20.i.i
+	br i1 false, label %bb22.i.i, label %bb24.i.i
+
+bb22.i.i:		; preds = %bb21.i.i
+	br i1 false, label %bb23.i.i, label %bb24.i.i
+
+bb23.i.i:		; preds = %bb22.i.i
+	br label %bb24.i.i
+
+bb24.i.i:		; preds = %bb23.i.i, %bb22.i.i, %bb21.i.i, %bb20.i.i
+	br i1 false, label %bb26.i.i, label %sat.exit.i.loopexit.loopexit
+
+bb26.i.i:		; preds = %bb24.i.i
+	br i1 false, label %bb27.i.i, label %bb33.i.i.loopexit
+
+bb27.i.i:		; preds = %bb26.i.i
+	br i1 false, label %bb33.i.i.loopexit, label %bb28.i.i
+
+bb28.i.i:		; preds = %bb27.i.i
+	br i1 false, label %bb1.i55.i.i, label %bb13.i.i71.backedge
+
+bb1.i55.i.i:		; preds = %bb28.i.i
+	br i1 false, label %bb29.i.i, label %bb13.i.i71.backedge
+
+bb29.i.i:		; preds = %bb1.i55.i.i
+	br i1 false, label %bb31.i.i, label %sat.exit.i.loopexit.loopexit2
+
+bb31.i.i:		; preds = %bb29.i.i
+	br i1 false, label %bb33.i.i, label %bb1.i48.i.i
+
+bb1.i48.i.i:		; preds = %bb31.i.i
+	br i1 false, label %sat.exit.i.loopexit.loopexit2, label %bb33.i.i
+
+bb33.i.i.loopexit:		; preds = %bb27.i.i, %bb26.i.i
+	br label %bb33.i.i
+
+bb33.i.i:		; preds = %bb33.i.i.loopexit, %bb1.i48.i.i, %bb31.i.i
+	br i1 false, label %bb34.i.i, label %bb35.i.i
+
+bb34.i.i:		; preds = %bb33.i.i
+	br i1 false, label %bb35.i.i, label %bb2.i44.i.i76
+
+bb2.i44.i.i76:		; preds = %bb34.i.i
+	br label %bb35.i.i
+
+bb35.i.i:		; preds = %bb2.i44.i.i76, %bb34.i.i, %bb33.i.i
+	br i1 false, label %bb1.i37.i.i, label %bb.i35.i.i
+
+bb.i35.i.i:		; preds = %bb35.i.i
+	br label %bb36.i.i
+
+bb1.i37.i.i:		; preds = %bb35.i.i
+	br i1 false, label %bb37.i.i, label %bb36.i.i
+
+bb36.i.i:		; preds = %bb1.i37.i.i, %bb.i35.i.i
+	br label %bb25.i23.i.i
+
+bb.i18.i.i:		; preds = %bb25.i23.i.i
+	br i1 false, label %bb24.i22.i.i, label %bb22.i19.i.i
+
+bb22.i19.i.i:		; preds = %bb.i18.i.i
+	br label %bb24.i22.i.i
+
+bb24.i22.i.i:		; preds = %bb22.i19.i.i, %bb.i18.i.i
+	br label %bb25.i23.i.i
+
+bb25.i23.i.i:		; preds = %bb24.i22.i.i, %bb36.i.i
+	br i1 false, label %bb.i18.i.i, label %bb26.i24.i.i
+
+bb26.i24.i.i:		; preds = %bb25.i23.i.i
+	br i1 false, label %bb27.i25.i.i, label %bb32.i.i.i
+
+bb27.i25.i.i:		; preds = %bb26.i24.i.i
+	br label %bb32.i.i.i
+
+bb32.i.i.i:		; preds = %bb27.i25.i.i, %bb26.i24.i.i
+	br label %bb64.i.i.i
+
+bb33.i.i.i:		; preds = %bb64.i.i.i
+	br i1 false, label %bb60.i.i.i, label %bb34.i.i.i
+
+bb34.i.i.i:		; preds = %bb33.i.i.i
+	br i1 false, label %bb38.i.i.i, label %bb60.i.i.i
+
+bb38.i.i.i:		; preds = %bb34.i.i.i
+	br i1 false, label %bb39.i.i.i, label %bb48.i.i.i
+
+bb39.i.i.i:		; preds = %bb38.i.i.i
+	br i1 false, label %bb48.i.i.i, label %bb40.i.i.i
+
+bb40.i.i.i:		; preds = %bb39.i.i.i
+	br i1 false, label %bb60.i.i.i, label %bb45.i.i.i
+
+bb45.i.i.i:		; preds = %bb40.i.i.i
+	br label %bb60.i.i.i
+
+bb48.i.i.i:		; preds = %bb39.i.i.i, %bb38.i.i.i
+	br i1 false, label %bb53.i.i.i, label %bb60.i.i.i
+
+bb53.i.i.i:		; preds = %bb48.i.i.i
+	br i1 false, label %bb60.i.i.i, label %bb58.i.i.i
+
+bb58.i.i.i:		; preds = %bb53.i.i.i
+	br i1 false, label %bb59.i.i.i, label %bb60.i.i.i
+
+bb59.i.i.i:		; preds = %bb58.i.i.i
+	br label %bb60.i.i.i
+
+bb60.i.i.i:		; preds = %bb59.i.i.i, %bb58.i.i.i, %bb53.i.i.i, %bb48.i.i.i, %bb45.i.i.i, %bb40.i.i.i, %bb34.i.i.i, %bb33.i.i.i
+	%lcollect.i.i.i.1 = phi i32 [ %lcollect.i.i.i.2, %bb34.i.i.i ], [ %lcollect.i.i.i.2, %bb48.i.i.i ], [ %lcollect.i.i.i.2, %bb58.i.i.i ], [ %lcollect.i.i.i.2, %bb59.i.i.i ], [ %lcollect.i.i.i.2, %bb53.i.i.i ], [ %lcollect.i.i.i.2, %bb33.i.i.i ], [ %lcollect.i.i.i.2, %bb40.i.i.i ], [ 0, %bb45.i.i.i ]		;  [#uses=1]
+	br label %bb64.i.i.i
+
+bb64.i.i.i:		; preds = %bb60.i.i.i, %bb32.i.i.i
+	%lcollect.i.i.i.2 = phi i32 [ 0, %bb32.i.i.i ], [ %lcollect.i.i.i.1, %bb60.i.i.i ]		;  [#uses=8]
+	br i1 false, label %bb65.i.i.i, label %bb33.i.i.i
+
+bb65.i.i.i:		; preds = %bb64.i.i.i
+	br i1 false, label %bb103.i.i.i.preheader, label %bb66.i.i.i.preheader
+
+bb66.i.i.i.preheader:		; preds = %bb65.i.i.i
+	br label %bb66.i.i.i
+
+bb66.i.i.i:		; preds = %bb66.i.i.i.backedge, %bb66.i.i.i.preheader
+	br i1 false, label %bb67.i.i.i, label %bb68.i.i.i
+
+bb67.i.i.i:		; preds = %bb66.i.i.i
+	br label %bb68.i.i.i
+
+bb68.i.i.i:		; preds = %bb67.i.i.i, %bb66.i.i.i
+	br i1 false, label %bb69.i.i.i, label %bb70.i.i.i
+
+bb69.i.i.i:		; preds = %bb68.i.i.i
+	br label %bb70.i.i.i
+
+bb70.i.i.i:		; preds = %bb69.i.i.i, %bb68.i.i.i
+	br i1 false, label %bb71.i.i.i, label %bb72.i.i.i
+
+bb71.i.i.i:		; preds = %bb70.i.i.i
+	br label %bb72.i.i.i
+
+bb72.i.i.i:		; preds = %bb71.i.i.i, %bb70.i.i.i
+	br label %bb73.i.i.i.outer
+
+bb73.i.i.i.outer:		; preds = %bb78.i.i.i, %bb72.i.i.i
+	br label %bb73.i.i.i
+
+bb73.i.i.i:		; preds = %bb73.i.i.i, %bb73.i.i.i.outer
+	br i1 false, label %bb73.i.i.i, label %bb76.i.i.i.preheader
+
+bb76.i.i.i.preheader:		; preds = %bb73.i.i.i
+	br label %bb76.i.i.i
+
+bb76.i.i.i:		; preds = %bb76.i.i.i, %bb76.i.i.i.preheader
+	br i1 false, label %bb77.i.i.i, label %bb76.i.i.i
+
+bb77.i.i.i:		; preds = %bb76.i.i.i
+	br i1 false, label %bb78.i.i.i, label %bb79.i.i.i
+
+bb78.i.i.i:		; preds = %bb77.i.i.i
+	br label %bb73.i.i.i.outer
+
+bb79.i.i.i:		; preds = %bb77.i.i.i
+	br i1 false, label %bb83.i.i.i, label %bb94.i.i.i
+
+bb83.i.i.i:		; preds = %bb79.i.i.i
+	br i1 false, label %bb84.i.i.i, label %bb88.i.i.i
+
+bb84.i.i.i:		; preds = %bb83.i.i.i
+	br i1 false, label %bb87.i.i.i, label %bb85.i.i.i
+
+bb85.i.i.i:		; preds = %bb84.i.i.i
+	br label %bb87.i.i.i
+
+bb87.i.i.i:		; preds = %bb85.i.i.i, %bb84.i.i.i
+	br label %bb88.i.i.i
+
+bb88.i.i.i:		; preds = %bb87.i.i.i, %bb83.i.i.i
+	br i1 false, label %bb89.i.i.i, label %bb93.i.i.i
+
+bb89.i.i.i:		; preds = %bb88.i.i.i
+	br i1 false, label %bb92.i.i.i, label %bb90.i.i.i
+
+bb90.i.i.i:		; preds = %bb89.i.i.i
+	br label %bb92.i.i.i
+
+bb92.i.i.i:		; preds = %bb90.i.i.i, %bb89.i.i.i
+	br label %bb93.i.i.i
+
+bb93.i.i.i:		; preds = %bb92.i.i.i, %bb88.i.i.i
+	br label %bb66.i.i.i.backedge
+
+bb66.i.i.i.backedge:		; preds = %bb97.i.i.i, %bb94.i.i.i, %bb93.i.i.i
+	br label %bb66.i.i.i
+
+bb94.i.i.i:		; preds = %bb79.i.i.i
+	br i1 false, label %bb66.i.i.i.backedge, label %bb96.i.i.i
+
+bb96.i.i.i:		; preds = %bb94.i.i.i
+	br i1 false, label %bb97.i.i.i, label %bb103.i.i.i.preheader.loopexit
+
+bb103.i.i.i.preheader.loopexit:		; preds = %bb96.i.i.i
+	br label %bb103.i.i.i.preheader
+
+bb103.i.i.i.preheader:		; preds = %bb103.i.i.i.preheader.loopexit, %bb65.i.i.i
+	br label %bb103.i.i.i
+
+bb97.i.i.i:		; preds = %bb96.i.i.i
+	br label %bb66.i.i.i.backedge
+
+bb100.i.i.i:		; preds = %bb103.i.i.i
+	br i1 false, label %bb101.i.i.i, label %bb102.i.i.i
+
+bb101.i.i.i:		; preds = %bb100.i.i.i
+	br label %bb102.i.i.i
+
+bb102.i.i.i:		; preds = %bb101.i.i.i, %bb100.i.i.i
+	br label %bb103.i.i.i
+
+bb103.i.i.i:		; preds = %bb102.i.i.i, %bb103.i.i.i.preheader
+	br i1 false, label %bb100.i.i.i, label %bb109.i.i.i.preheader
+
+bb109.i.i.i.preheader:		; preds = %bb103.i.i.i
+	br label %bb109.i.i.i
+
+bb105.i.i.i:		; preds = %bb109.i.i.i
+	br label %bb107.i.i.i
+
+bb106.i.i.i:		; preds = %bb107.i.i.i
+	br label %bb107.i.i.i
+
+bb107.i.i.i:		; preds = %bb106.i.i.i, %bb105.i.i.i
+	br i1 false, label %bb106.i.i.i, label %bb108.i.i.i
+
+bb108.i.i.i:		; preds = %bb107.i.i.i
+	br label %bb109.i.i.i
+
+bb109.i.i.i:		; preds = %bb108.i.i.i, %bb109.i.i.i.preheader
+	br i1 false, label %bb110.i.i.i, label %bb105.i.i.i
+
+bb110.i.i.i:		; preds = %bb109.i.i.i
+	%0 = sub i32 0, %lcollect.i.i.i.2		;  [#uses=1]
+	%1 = add i32 %0, 1		;  [#uses=1]
+	br label %bb113.i.i.i
+
+bb111.i.i.i:		; preds = %bb113.i.i.i
+	br i1 false, label %bb114.i.i.i, label %bb113.i.i.i
+
+bb113.i.i.i:		; preds = %bb111.i.i.i, %bb110.i.i.i
+	br i1 false, label %bb111.i.i.i, label %bb114.i.i.i
+
+bb114.i.i.i:		; preds = %bb113.i.i.i, %bb111.i.i.i
+	%2 = lshr i32 %1, 1		;  [#uses=2]
+	br i1 false, label %bb116.i.i.i, label %bb124.i.i.i
+
+bb116.i.i.i:		; preds = %bb114.i.i.i
+	br i1 false, label %bb117.i.i.i.preheader, label %bb122.i.i.i.preheader
+
+bb122.i.i.i.preheader:		; preds = %bb116.i.i.i
+	br label %bb122.i.i.i
+
+bb117.i.i.i.preheader:		; preds = %bb116.i.i.i
+	br label %bb117.i.i.i
+
+bb117.i.i.i:		; preds = %bb118.i.i.i, %bb117.i.i.i.preheader
+	%target.i.i.i.1 = phi i32 [ %3, %bb118.i.i.i ], [ %2, %bb117.i.i.i.preheader ]		;  [#uses=1]
+	%3 = add i32 %target.i.i.i.1, 1		;  [#uses=2]
+	br i1 false, label %bb118.i.i.i, label %bb124.i.i.i.loopexit
+
+bb118.i.i.i:		; preds = %bb117.i.i.i
+	br i1 false, label %bb117.i.i.i, label %bb124.i.i.i.loopexit
+
+bb122.i.i.i:		; preds = %bb123.i.i.i, %bb122.i.i.i.preheader
+	%target.i.i.i.2 = phi i32 [ %4, %bb123.i.i.i ], [ %2, %bb122.i.i.i.preheader ]		;  [#uses=2]
+	br i1 false, label %bb124.i.i.i.loopexit1, label %bb123.i.i.i
+
+bb123.i.i.i:		; preds = %bb122.i.i.i
+	%4 = add i32 %target.i.i.i.2, -1		;  [#uses=1]
+	br i1 false, label %bb122.i.i.i, label %bb124.i.i.i.loopexit1
+
+bb124.i.i.i.loopexit:		; preds = %bb118.i.i.i, %bb117.i.i.i
+	br label %bb124.i.i.i
+
+bb124.i.i.i.loopexit1:		; preds = %bb123.i.i.i, %bb122.i.i.i
+	br label %bb124.i.i.i
+
+bb124.i.i.i:		; preds = %bb124.i.i.i.loopexit1, %bb124.i.i.i.loopexit, %bb114.i.i.i
+	%target.i.i.i.0 = phi i32 [ 0, %bb114.i.i.i ], [ %3, %bb124.i.i.i.loopexit ], [ %target.i.i.i.2, %bb124.i.i.i.loopexit1 ]		;  [#uses=0]
+	br label %bb132.i.i.i.outer
+
+bb125.i.i.i:		; preds = %bb132.i.i.i
+	br i1 false, label %bb132.i.i.i, label %bb130.i.i.i
+
+bb130.i.i.i:		; preds = %bb125.i.i.i
+	br label %bb132.i.i.i.outer
+
+bb132.i.i.i.outer:		; preds = %bb130.i.i.i, %bb124.i.i.i
+	br label %bb132.i.i.i
+
+bb132.i.i.i:		; preds = %bb132.i.i.i.outer, %bb125.i.i.i
+	br i1 false, label %bb125.i.i.i, label %bb133.i.i.i
+
+bb133.i.i.i:		; preds = %bb132.i.i.i
+	br i1 false, label %bb136.i.i.i, label %bb134.i.i.i
+
+bb134.i.i.i:		; preds = %bb133.i.i.i
+	br i1 false, label %bb136.i.i.i, label %bb135.i.i.i
+
+bb135.i.i.i:		; preds = %bb134.i.i.i
+	br label %bb136.i.i.i
+
+bb136.i.i.i:		; preds = %bb135.i.i.i, %bb134.i.i.i, %bb133.i.i.i
+	br i1 false, label %bb137.i.i.i, label %bb37.i.i
+
+bb137.i.i.i:		; preds = %bb136.i.i.i
+	br label %bb37.i.i
+
+bb37.i.i:		; preds = %bb137.i.i.i, %bb136.i.i.i, %bb1.i37.i.i
+	br i1 false, label %bb40.i.i, label %bb38.i.i
+
+bb38.i.i:		; preds = %bb37.i.i
+	br i1 false, label %bb39.i.i, label %bb40.i.i
+
+bb39.i.i:		; preds = %bb38.i.i
+	br i1 false, label %bb17.i.i.i, label %bb3.i12.i.i
+
+bb3.i12.i.i:		; preds = %bb39.i.i
+	br label %bb5.i14.i.i
+
+bb5.i14.i.i:		; preds = %bb8.i.i.i79, %bb3.i12.i.i
+	br i1 false, label %bb6.i15.i.i, label %bb9.i.i.i80
+
+bb6.i15.i.i:		; preds = %bb5.i14.i.i
+	br i1 false, label %bb7.i.i.i78, label %bb9.i.i.i80
+
+bb7.i.i.i78:		; preds = %bb6.i15.i.i
+	br i1 false, label %bb9.i.i.i80, label %bb8.i.i.i79
+
+bb8.i.i.i79:		; preds = %bb7.i.i.i78
+	br i1 false, label %bb9.i.i.i80, label %bb5.i14.i.i
+
+bb9.i.i.i80:		; preds = %bb8.i.i.i79, %bb7.i.i.i78, %bb6.i15.i.i, %bb5.i14.i.i
+	br i1 false, label %bb16.i.i.i, label %bb10.i.i.i81
+
+bb10.i.i.i81:		; preds = %bb9.i.i.i80
+	br i1 false, label %bb11.i.i.i, label %bb15.i.i.i
+
+bb11.i.i.i:		; preds = %bb10.i.i.i81
+	br i1 false, label %bb16.i.i.i, label %bb15.i.i.i
+
+bb15.i.i.i:		; preds = %bb11.i.i.i, %bb10.i.i.i81
+	br label %bb16.i.i.i
+
+bb16.i.i.i:		; preds = %bb15.i.i.i, %bb11.i.i.i, %bb9.i.i.i80
+	br label %bb17.i.i.i
+
+bb17.i.i.i:		; preds = %bb16.i.i.i, %bb39.i.i
+	br i1 false, label %bb18.i.i.i, label %bb25.i.i.i
+
+bb18.i.i.i:		; preds = %bb17.i.i.i
+	br i1 false, label %bb24.i.i.i, label %bb23.i.i.i
+
+bb23.i.i.i:		; preds = %bb18.i.i.i
+	br label %bb24.i.i.i
+
+bb24.i.i.i:		; preds = %bb23.i.i.i, %bb18.i.i.i
+	br label %bb29.i.i.i
+
+bb25.i.i.i:		; preds = %bb17.i.i.i
+	br i1 false, label %bb29.i.i.i, label %bb27.i.i.i
+
+bb27.i.i.i:		; preds = %bb25.i.i.i
+	br i1 false, label %bb29.i.i.i, label %bb28.i.i.i
+
+bb28.i.i.i:		; preds = %bb27.i.i.i
+	br i1 false, label %bb29.i.i.i, label %bb.i4.i.i.i
+
+bb.i4.i.i.i:		; preds = %bb28.i.i.i
+	br i1 false, label %bb4.i.i16.i.i, label %bb29.i.i.i
+
+bb4.i.i16.i.i:		; preds = %bb.i4.i.i.i
+	br label %bb29.i.i.i
+
+bb29.i.i.i:		; preds = %bb4.i.i16.i.i, %bb.i4.i.i.i, %bb28.i.i.i, %bb27.i.i.i, %bb25.i.i.i, %bb24.i.i.i
+	br label %bb40.i.i
+
+bb40.i.i:		; preds = %bb29.i.i.i, %bb38.i.i, %bb37.i.i
+	br i1 false, label %bb9.i.i.i.i.preheader, label %bb2.i.i.i87
+
+bb9.i.i.i.i.preheader:		; preds = %bb40.i.i
+	br label %bb9.i.i.i.i
+
+bb.i.i.i.i84:		; preds = %bb9.i.i.i.i
+	switch i8 0, label %bb8.i.i.i.i [
+		i8 -1, label %bb1.i.i.i.i85
+		i8 1, label %bb9.i.i.i.i
+	]
+
+bb1.i.i.i.i85:		; preds = %bb.i.i.i.i84
+	br i1 false, label %bb5.i.i.i.i, label %bb2.i.i.i87
+
+bb5.i.i.i.i:		; preds = %bb1.i.i.i.i85
+	br label %bb2.i.i.i87
+
+bb8.i.i.i.i:		; preds = %bb.i.i.i.i84
+	br i1 false, label %bb2.i.i.i87, label %bb6.i.i.i95
+
+bb9.i.i.i.i:		; preds = %bb.i.i.i.i84, %bb9.i.i.i.i.preheader
+	br i1 false, label %bb.i.i.i.i84, label %bb10.i.i.i.i
+
+bb10.i.i.i.i:		; preds = %bb9.i.i.i.i
+	br label %bb2.i.i.i87
+
+bb2.i.i.i87:		; preds = %bb10.i.i.i.i, %bb8.i.i.i.i, %bb5.i.i.i.i, %bb1.i.i.i.i85, %bb40.i.i
+	br i1 false, label %bb3.i.i.i88, label %decide.exit.i.i
+
+bb3.i.i.i88:		; preds = %bb2.i.i.i87
+	br i1 false, label %bb4.i.i.i90, label %bb1.i23.i.i.i
+
+bb1.i23.i.i.i:		; preds = %bb3.i.i.i88
+	br i1 false, label %decide.exit.i.i, label %bb4.i.i.i90
+
+bb4.i.i.i90:		; preds = %bb1.i23.i.i.i, %bb3.i.i.i88
+	br i1 false, label %bb1.i9.i.i.i, label %bb5.i.i.i94
+
+bb1.i9.i.i.i:		; preds = %bb4.i.i.i90
+	br i1 false, label %bb.i.i27.i.i.i.i, label %bb1.i.i28.i.i.i.i
+
+bb.i.i27.i.i.i.i:		; preds = %bb1.i9.i.i.i
+	br label %int2lit.exit32.i.i.i.i
+
+bb1.i.i28.i.i.i.i:		; preds = %bb1.i9.i.i.i
+	br label %int2lit.exit32.i.i.i.i
+
+int2lit.exit32.i.i.i.i:		; preds = %bb1.i.i28.i.i.i.i, %bb.i.i27.i.i.i.i
+	br i1 false, label %bb8.i19.i.i.i, label %bb2.i.i.i.i91
+
+bb2.i.i.i.i91:		; preds = %int2lit.exit32.i.i.i.i
+	br label %bb4.i.i.i.i
+
+bb3.i.i.i.i92:		; preds = %gcd.exit.i.i.i.i
+	br label %bb4.i.i.i.i
+
+bb4.i.i.i.i:		; preds = %bb3.i.i.i.i92, %bb2.i.i.i.i91
+	br label %bb3.i.i13.i.i.i
+
+bb2.i.i12.i.i.i:		; preds = %bb3.i.i13.i.i.i
+	br label %bb3.i.i13.i.i.i
+
+bb3.i.i13.i.i.i:		; preds = %bb2.i.i12.i.i.i, %bb4.i.i.i.i
+	br i1 false, label %gcd.exit.i.i.i.i, label %bb2.i.i12.i.i.i
+
+gcd.exit.i.i.i.i:		; preds = %bb3.i.i13.i.i.i
+	br i1 false, label %bb5.i14.i.i.i.preheader, label %bb3.i.i.i.i92
+
+bb5.i14.i.i.i.preheader:		; preds = %gcd.exit.i.i.i.i
+	br label %bb5.i14.i.i.i
+
+bb5.i14.i.i.i:		; preds = %int2lit.exit.i.i.i.i, %bb5.i14.i.i.i.preheader
+	br i1 false, label %bb.i.i.i17.i.i.i, label %bb1.i.i.i18.i.i.i
+
+bb.i.i.i17.i.i.i:		; preds = %bb5.i14.i.i.i
+	br label %int2lit.exit.i.i.i.i
+
+bb1.i.i.i18.i.i.i:		; preds = %bb5.i14.i.i.i
+	br label %int2lit.exit.i.i.i.i
+
+int2lit.exit.i.i.i.i:		; preds = %bb1.i.i.i18.i.i.i, %bb.i.i.i17.i.i.i
+	br i1 false, label %bb8.i19.i.i.i.loopexit, label %bb5.i14.i.i.i
+
+bb8.i19.i.i.i.loopexit:		; preds = %int2lit.exit.i.i.i.i
+	br label %bb8.i19.i.i.i
+
+bb8.i19.i.i.i:		; preds = %bb8.i19.i.i.i.loopexit, %int2lit.exit32.i.i.i.i
+	br i1 false, label %bb5.i.i.i94, label %bb6.i.i.i95
+
+bb5.i.i.i94:		; preds = %bb8.i19.i.i.i, %bb4.i.i.i90
+	br label %bb.i2.i.i.i
+
+bb.i2.i.i.i:		; preds = %hpop.exit.i.i.i.i, %bb5.i.i.i94
+	br i1 false, label %hpop.exit.i.i.i.i, label %bb1.i.i.i.i.i
+
+bb1.i.i.i.i.i:		; preds = %bb.i2.i.i.i
+	br label %bb2.i.i.i.i.i
+
+bb2.i.i.i.i.i:		; preds = %bb11.i.i.i.i.i, %bb1.i.i.i.i.i
+	br i1 false, label %bb3.i.i.i.i.i, label %bb12.i.i.i.i.i
+
+bb3.i.i.i.i.i:		; preds = %bb2.i.i.i.i.i
+	br i1 false, label %bb4.i.i.i.i.i, label %bb1.i.i.i.i.i.i
+
+bb1.i.i.i.i.i.i:		; preds = %bb3.i.i.i.i.i
+	br i1 false, label %bb8.i.i.i.i.i, label %bb3.i.i.i.i.i.i
+
+bb3.i.i.i.i.i.i:		; preds = %bb1.i.i.i.i.i.i
+	br i1 false, label %bb4.i.i.i.i.i, label %bb8.i.i.i.i.i
+
+bb4.i.i.i.i.i:		; preds = %bb3.i.i.i.i.i.i, %bb3.i.i.i.i.i
+	br i1 false, label %bb5.i.i.i.i.i, label %bb11.i.i.i.i.i
+
+bb5.i.i.i.i.i:		; preds = %bb4.i.i.i.i.i
+	br i1 false, label %bb6.i.i.i.i.i, label %bb1.i21.i.i.i.i.i
+
+bb1.i21.i.i.i.i.i:		; preds = %bb5.i.i.i.i.i
+	br i1 false, label %bb11.i.i.i.i.i, label %bb3.i24.i.i.i.i.i
+
+bb3.i24.i.i.i.i.i:		; preds = %bb1.i21.i.i.i.i.i
+	br i1 false, label %bb6.i.i.i.i.i, label %bb11.i.i.i.i.i
+
+bb6.i.i.i.i.i:		; preds = %bb3.i24.i.i.i.i.i, %bb5.i.i.i.i.i
+	br label %bb11.i.i.i.i.i
+
+bb8.i.i.i.i.i:		; preds = %bb3.i.i.i.i.i.i, %bb1.i.i.i.i.i.i
+	br i1 false, label %bb9.i.i.i.i.i, label %bb12.i.i.i.i.i
+
+bb9.i.i.i.i.i:		; preds = %bb8.i.i.i.i.i
+	br i1 false, label %bb11.i.i.i.i.i, label %bb1.i8.i.i.i.i.i
+
+bb1.i8.i.i.i.i.i:		; preds = %bb9.i.i.i.i.i
+	br i1 false, label %bb12.i.i.i.i.i, label %bb3.i11.i.i.i.i.i
+
+bb3.i11.i.i.i.i.i:		; preds = %bb1.i8.i.i.i.i.i
+	br i1 false, label %bb11.i.i.i.i.i, label %bb12.i.i.i.i.i
+
+bb11.i.i.i.i.i:		; preds = %bb3.i11.i.i.i.i.i, %bb9.i.i.i.i.i, %bb6.i.i.i.i.i, %bb3.i24.i.i.i.i.i, %bb1.i21.i.i.i.i.i, %bb4.i.i.i.i.i
+	br label %bb2.i.i.i.i.i
+
+bb12.i.i.i.i.i:		; preds = %bb3.i11.i.i.i.i.i, %bb1.i8.i.i.i.i.i, %bb8.i.i.i.i.i, %bb2.i.i.i.i.i
+	br label %hpop.exit.i.i.i.i
+
+hpop.exit.i.i.i.i:		; preds = %bb12.i.i.i.i.i, %bb.i2.i.i.i
+	br i1 false, label %sdecide.exit.i.i.i, label %bb.i2.i.i.i
+
+sdecide.exit.i.i.i:		; preds = %hpop.exit.i.i.i.i
+	br label %bb6.i.i.i95
+
+bb6.i.i.i95:		; preds = %sdecide.exit.i.i.i, %bb8.i19.i.i.i, %bb8.i.i.i.i
+	br label %decide.exit.i.i
+
+decide.exit.i.i:		; preds = %bb6.i.i.i95, %bb1.i23.i.i.i, %bb2.i.i.i87
+	br i1 false, label %bb42.i.i, label %sat.exit.i.loopexit.loopexit2
+
+bb42.i.i:		; preds = %decide.exit.i.i
+	br label %bb13.i.i71.outer
+
+sat.exit.i.loopexit.loopexit:		; preds = %bb24.i.i, %bb1.i68.i.i, %incincs.exit.i.i
+	br label %sat.exit.i.loopexit
+
+sat.exit.i.loopexit.loopexit2:		; preds = %decide.exit.i.i, %bb1.i48.i.i, %bb29.i.i
+	br label %sat.exit.i.loopexit
+
+sat.exit.i.loopexit:		; preds = %sat.exit.i.loopexit.loopexit2, %sat.exit.i.loopexit.loopexit
+	br label %sat.exit.i
+
+sat.exit.i:		; preds = %sat.exit.i.loopexit, %bb1.i61.i.i, %bb8.i.i67, %bb1.i.i.i63, %bb3.i.i59
+	br i1 false, label %bb7.i, label %bb2.i96
+
+bb2.i96:		; preds = %sat.exit.i
+	switch i32 0, label %bb5.i99 [
+		i32 10, label %bb4.i98
+		i32 20, label %bb6.i100
+	]
+
+bb4.i98:		; preds = %bb2.i96
+	br label %bb6.i100
+
+bb5.i99:		; preds = %bb2.i96
+	br label %bb6.i100
+
+bb6.i100:		; preds = %bb5.i99, %bb4.i98, %bb2.i96
+	br label %bb7.i
+
+bb7.i:		; preds = %bb6.i100, %sat.exit.i
+	br i1 false, label %bb.i1.i, label %picosat_sat.exit
+
+bb.i1.i:		; preds = %bb7.i
+	br label %picosat_sat.exit
+
+picosat_sat.exit:		; preds = %bb.i1.i, %bb7.i
+	switch i32 0, label %bb166 [
+		i32 20, label %bb150
+		i32 10, label %bb163
+	]
+
+bb150:		; preds = %picosat_sat.exit
+	br i1 false, label %bb152, label %bb151
+
+bb151:		; preds = %bb150
+	br label %bb152
+
+bb152:		; preds = %bb151, %bb150
+	br i1 false, label %bb154, label %bb153
+
+bb153:		; preds = %bb152
+	br label %bb154
+
+bb154:		; preds = %bb153, %bb152
+	br i1 false, label %bb157, label %bb156
+
+bb156:		; preds = %bb154
+	br label %bb157
+
+bb157:		; preds = %bb156, %bb154
+	br i1 false, label %bb159, label %bb158
+
+bb158:		; preds = %bb157
+	br label %bb159
+
+bb159:		; preds = %bb158, %bb157
+	br i1 false, label %bb167, label %bb160
+
+bb160:		; preds = %bb159
+	br label %bb167
+
+bb163:		; preds = %picosat_sat.exit
+	br i1 false, label %bb167, label %bb164
+
+bb164:		; preds = %bb163
+	br label %bb4.i
+
+bb.i11:		; preds = %bb4.i
+	br i1 false, label %bb.i.i12, label %bb1.i.i14
+
+bb.i.i12:		; preds = %bb.i11
+	unreachable
+
+bb1.i.i14:		; preds = %bb.i11
+	br i1 false, label %bb3.i.i16, label %bb2.i.i15
+
+bb2.i.i15:		; preds = %bb1.i.i14
+	unreachable
+
+bb3.i.i16:		; preds = %bb1.i.i14
+	br i1 false, label %bb3.i, label %bb7.i.i
+
+bb7.i.i:		; preds = %bb3.i.i16
+	br i1 false, label %bb.i.i.i.i17, label %bb1.i.i.i.i18
+
+bb.i.i.i.i17:		; preds = %bb7.i.i
+	br label %int2lit.exit.i.i
+
+bb1.i.i.i.i18:		; preds = %bb7.i.i
+	br label %int2lit.exit.i.i
+
+int2lit.exit.i.i:		; preds = %bb1.i.i.i.i18, %bb.i.i.i.i17
+	br i1 false, label %bb3.i, label %bb9.i.i
+
+bb9.i.i:		; preds = %int2lit.exit.i.i
+	br label %bb3.i
+
+bb3.i:		; preds = %bb9.i.i, %int2lit.exit.i.i, %bb3.i.i16
+	br label %bb4.i
+
+bb4.i:		; preds = %bb3.i, %bb164
+	br i1 false, label %bb5.i, label %bb.i11
+
+bb5.i:		; preds = %bb4.i
+	br i1 false, label %bb6.i, label %bb167
+
+bb6.i:		; preds = %bb5.i
+	br label %bb167
+
+bb166:		; preds = %picosat_sat.exit
+	br label %bb167
+
+bb167:		; preds = %bb166, %bb6.i, %bb5.i, %bb163, %bb160, %bb159, %picosat_print.exit
+	br i1 false, label %bb168, label %bb170
+
+bb168:		; preds = %bb167
+	br i1 false, label %bb170, label %bb169
+
+bb169:		; preds = %bb168
+	br i1 false, label %bb.i7, label %picosat_time_stamp.exit9
+
+bb.i7:		; preds = %bb169
+	br label %picosat_time_stamp.exit9
+
+picosat_time_stamp.exit9:		; preds = %bb.i7, %bb169
+	br label %bb170
+
+bb170:		; preds = %picosat_time_stamp.exit9, %bb168, %bb167, %bb129
+	br i1 false, label %bb.i.i3, label %picosat_leave.exit
+
+bb.i.i3:		; preds = %bb170
+	br label %picosat_leave.exit
+
+picosat_leave.exit:		; preds = %bb.i.i3, %bb170
+	br i1 false, label %bb1.i.i, label %bb.i.i
+
+bb.i.i:		; preds = %picosat_leave.exit
+	unreachable
+
+bb1.i.i:		; preds = %picosat_leave.exit
+	br label %bb9.i.i.i
+
+bb3.i.i.i:		; preds = %bb9.i.i.i
+	br i1 false, label %bb5.i.i.i, label %bb4.i.i.i
+
+bb4.i.i.i:		; preds = %bb3.i.i.i
+	br label %bb5.i.i.i
+
+bb5.i.i.i:		; preds = %bb4.i.i.i, %bb3.i.i.i
+	br label %bb9.i.i.i
+
+bb9.i.i.i:		; preds = %bb5.i.i.i, %bb1.i.i
+	br i1 false, label %bb10.i.i.i, label %bb3.i.i.i
+
+bb10.i.i.i:		; preds = %bb9.i.i.i
+	br i1 false, label %delete.exit.i.i.i, label %bb1.i.i.i.i
+
+bb1.i.i.i.i:		; preds = %bb10.i.i.i
+	br label %delete.exit.i.i.i
+
+delete.exit.i.i.i:		; preds = %bb1.i.i.i.i, %bb10.i.i.i
+	br i1 false, label %delete_clauses.exit.i.i, label %bb1.i7.i.i.i
+
+bb1.i7.i.i.i:		; preds = %delete.exit.i.i.i
+	br label %delete_clauses.exit.i.i
+
+delete_clauses.exit.i.i:		; preds = %bb1.i7.i.i.i, %delete.exit.i.i.i
+	br label %bb3.i.i
+
+bb2.i.i:		; preds = %bb3.i.i
+	br i1 false, label %lrelease.exit.i.i, label %bb1.i.i23.i.i
+
+bb1.i.i23.i.i:		; preds = %bb2.i.i
+	br label %lrelease.exit.i.i
+
+lrelease.exit.i.i:		; preds = %bb1.i.i23.i.i, %bb2.i.i
+	br label %bb3.i.i
+
+bb3.i.i:		; preds = %lrelease.exit.i.i, %delete_clauses.exit.i.i
+	br i1 false, label %bb4.i.i, label %bb2.i.i
+
+bb4.i.i:		; preds = %bb3.i.i
+	br i1 false, label %delete.exit214.i.i, label %bb1.i208.i.i
+
+bb1.i208.i.i:		; preds = %bb4.i.i
+	br label %delete.exit214.i.i
+
+delete.exit214.i.i:		; preds = %bb1.i208.i.i, %bb4.i.i
+	br i1 false, label %delete.exit203.i.i, label %bb1.i197.i.i
+
+bb1.i197.i.i:		; preds = %delete.exit214.i.i
+	br label %delete.exit203.i.i
+
+delete.exit203.i.i:		; preds = %bb1.i197.i.i, %delete.exit214.i.i
+	br i1 false, label %delete.exit192.i.i, label %bb1.i186.i.i
+
+bb1.i186.i.i:		; preds = %delete.exit203.i.i
+	br label %delete.exit192.i.i
+
+delete.exit192.i.i:		; preds = %bb1.i186.i.i, %delete.exit203.i.i
+	br i1 false, label %delete.exit181.i.i, label %bb1.i175.i.i
+
+bb1.i175.i.i:		; preds = %delete.exit192.i.i
+	br label %delete.exit181.i.i
+
+delete.exit181.i.i:		; preds = %bb1.i175.i.i, %delete.exit192.i.i
+	br i1 false, label %delete.exit170.i.i, label %bb1.i164.i.i
+
+bb1.i164.i.i:		; preds = %delete.exit181.i.i
+	br label %delete.exit170.i.i
+
+delete.exit170.i.i:		; preds = %bb1.i164.i.i, %delete.exit181.i.i
+	br i1 false, label %delete.exit159.i.i, label %bb1.i153.i.i
+
+bb1.i153.i.i:		; preds = %delete.exit170.i.i
+	br label %delete.exit159.i.i
+
+delete.exit159.i.i:		; preds = %bb1.i153.i.i, %delete.exit170.i.i
+	br i1 false, label %delete.exit148.i.i, label %bb1.i142.i.i
+
+bb1.i142.i.i:		; preds = %delete.exit159.i.i
+	br label %delete.exit148.i.i
+
+delete.exit148.i.i:		; preds = %bb1.i142.i.i, %delete.exit159.i.i
+	br i1 false, label %delete.exit137.i.i, label %bb1.i131.i.i
+
+bb1.i131.i.i:		; preds = %delete.exit148.i.i
+	br label %delete.exit137.i.i
+
+delete.exit137.i.i:		; preds = %bb1.i131.i.i, %delete.exit148.i.i
+	br i1 false, label %delete.exit126.i.i, label %bb1.i120.i.i
+
+bb1.i120.i.i:		; preds = %delete.exit137.i.i
+	br label %delete.exit126.i.i
+
+delete.exit126.i.i:		; preds = %bb1.i120.i.i, %delete.exit137.i.i
+	br i1 false, label %delete.exit115.i.i, label %bb1.i109.i.i
+
+bb1.i109.i.i:		; preds = %delete.exit126.i.i
+	br label %delete.exit115.i.i
+
+delete.exit115.i.i:		; preds = %bb1.i109.i.i, %delete.exit126.i.i
+	br i1 false, label %delete.exit104.i.i, label %bb1.i98.i.i
+
+bb1.i98.i.i:		; preds = %delete.exit115.i.i
+	br label %delete.exit104.i.i
+
+delete.exit104.i.i:		; preds = %bb1.i98.i.i, %delete.exit115.i.i
+	br i1 false, label %delete.exit93.i.i, label %bb1.i87.i.i
+
+bb1.i87.i.i:		; preds = %delete.exit104.i.i
+	br label %delete.exit93.i.i
+
+delete.exit93.i.i:		; preds = %bb1.i87.i.i, %delete.exit104.i.i
+	br i1 false, label %delete.exit82.i.i, label %bb1.i76.i.i
+
+bb1.i76.i.i:		; preds = %delete.exit93.i.i
+	br label %delete.exit82.i.i
+
+delete.exit82.i.i:		; preds = %bb1.i76.i.i, %delete.exit93.i.i
+	br i1 false, label %delete.exit71.i.i, label %bb1.i65.i.i
+
+bb1.i65.i.i:		; preds = %delete.exit82.i.i
+	br label %delete.exit71.i.i
+
+delete.exit71.i.i:		; preds = %bb1.i65.i.i, %delete.exit82.i.i
+	br i1 false, label %delete.exit60.i.i, label %bb1.i54.i.i
+
+bb1.i54.i.i:		; preds = %delete.exit71.i.i
+	br label %delete.exit60.i.i
+
+delete.exit60.i.i:		; preds = %bb1.i54.i.i, %delete.exit71.i.i
+	br i1 false, label %delete.exit38.i.i, label %bb1.i32.i.i
+
+bb1.i32.i.i:		; preds = %delete.exit60.i.i
+	br label %delete.exit38.i.i
+
+delete.exit38.i.i:		; preds = %bb1.i32.i.i, %delete.exit60.i.i
+	br i1 false, label %delete.exit18.i.i, label %bb1.i12.i.i
+
+bb1.i12.i.i:		; preds = %delete.exit38.i.i
+	br label %delete.exit18.i.i
+
+delete.exit18.i.i:		; preds = %bb1.i12.i.i, %delete.exit38.i.i
+	br i1 false, label %picosat_reset.exit, label %bb1.i2.i.i
+
+bb1.i2.i.i:		; preds = %delete.exit18.i.i
+	br label %picosat_reset.exit
+
+picosat_reset.exit:		; preds = %bb1.i2.i.i, %delete.exit18.i.i
+	br label %bb171
+
+bb171:		; preds = %picosat_reset.exit, %bb110
+	br i1 false, label %bb173, label %bb172
+
+bb172:		; preds = %bb171
+	br label %bb173
+
+bb173:		; preds = %bb172, %bb171
+	br i1 false, label %bb175, label %bb174
+
+bb174:		; preds = %bb173
+	br label %bb175
+
+bb175:		; preds = %bb174, %bb173
+	br i1 false, label %bb177, label %bb176
+
+bb176:		; preds = %bb175
+	br label %bb177
+
+bb177:		; preds = %bb176, %bb175
+	br i1 false, label %bb179, label %bb178
+
+bb178:		; preds = %bb177
+	ret i32 0
+
+bb179:		; preds = %bb177
+	ret i32 0
+}
+
+define i32 @main(i32 %argc, i8** %argv) nounwind {
+entry:
+	br label %bb2
+
+bb:		; preds = %bb2
+	br i1 false, label %bb3, label %bb2
+
+bb2:		; preds = %bb, %entry
+	br i1 false, label %bb5.loopexit, label %bb
+
+bb3:		; preds = %bb
+	br i1 false, label %bb5, label %bb4
+
+bb4:		; preds = %bb3
+	br label %bb5
+
+bb5.loopexit:		; preds = %bb2
+	br label %bb5
+
+bb5:		; preds = %bb5.loopexit, %bb4, %bb3
+	%0 = call fastcc i32 @picosat_main(i32 %argc, i8** %argv) nounwind		;  [#uses=2]
+	br i1 false, label %bb7, label %bb6
+
+bb6:		; preds = %bb5
+	ret i32 %0
+
+bb7:		; preds = %bb5
+	ret i32 %0
+}




From resistor at mac.com  Wed Apr 22 23:24:20 2009
From: resistor at mac.com (Owen Anderson)
Date: Thu, 23 Apr 2009 04:24:20 -0000
Subject: [llvm-commits] [llvm] r69865 -
	/llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll
Message-ID: <200904230424.n3N4OKJ1007109@zion.cs.uiuc.edu>

Author: resistor
Date: Wed Apr 22 23:24:19 2009
New Revision: 69865

URL: http://llvm.org/viewvc/llvm-project?rev=69865&view=rev
Log:
Fix typo.

Modified:
    llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll

Modified: llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll?rev=69865&r1=69864&r2=69865&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll (original)
+++ llvm/trunk/test/Transforms/ArgumentPromotion/pr3085.ll Wed Apr 22 23:24:19 2009
@@ -1,5 +1,4 @@
-; RUN: llvm-as < %s | opt -disable-output -loop-extract-single -loop-rotate
--loop-reduce -argpromotion
+; RUN: llvm-as < %s | opt -disable-output -loop-extract-single -loop-rotate -loop-reduce -argpromotion
 ; PR 3085
 
 	%struct.Lit = type { i8 }




From resistor at mac.com  Wed Apr 22 23:26:43 2009
From: resistor at mac.com (Owen Anderson)
Date: Thu, 23 Apr 2009 04:26:43 -0000
Subject: [llvm-commits] [llvm] r69866 -
	/llvm/trunk/test/Transforms/LoopStrengthReduce/pr2537.ll
Message-ID: <200904230426.n3N4Qh6o007196@zion.cs.uiuc.edu>

Author: resistor
Date: Wed Apr 22 23:26:42 2009
New Revision: 69866

URL: http://llvm.org/viewvc/llvm-project?rev=69866&view=rev
Log:
Testcase for PR2537.

Added:
    llvm/trunk/test/Transforms/LoopStrengthReduce/pr2537.ll

Added: llvm/trunk/test/Transforms/LoopStrengthReduce/pr2537.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/pr2537.ll?rev=69866&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LoopStrengthReduce/pr2537.ll (added)
+++ llvm/trunk/test/Transforms/LoopStrengthReduce/pr2537.ll Wed Apr 22 23:26:42 2009
@@ -0,0 +1,21 @@
+; RUN: llvm-as < %s | opt -loop-reduce -disable-output
+; PR 2537
+
+define void @a() {
+entry:
+        br label %dobody
+
+dobody:         ; preds = %dobody, %entry
+        %y.0 = phi i128 [ 0, %entry ], [ %add, %dobody ]
+        %x.0 = phi i128 [ 0, %entry ], [ %add2, %dobody ]
+        %add = add i128 %y.0, shl (i128 1, i128 64)
+        %add2 = add i128 %x.0, shl (i128 1, i128 48)
+        call void @b( i128 %add )
+        %cmp = icmp ult i128 %add2, shl (i128 1, i128 64)
+        br i1 %cmp, label %dobody, label %afterdo
+
+afterdo:                ; preds = %dobody
+        ret void
+}
+
+declare void @b(i128 %add)
\ No newline at end of file




From resistor at mac.com  Wed Apr 22 23:30:52 2009
From: resistor at mac.com (Owen Anderson)
Date: Thu, 23 Apr 2009 04:30:52 -0000
Subject: [llvm-commits] [llvm] r69867 -
	/llvm/trunk/test/Transforms/LoopRotate/pr2639.ll
Message-ID: <200904230430.n3N4UqMx007323@zion.cs.uiuc.edu>

Author: resistor
Date: Wed Apr 22 23:30:52 2009
New Revision: 69867

URL: http://llvm.org/viewvc/llvm-project?rev=69867&view=rev
Log:
Testcase for PR2639.

Added:
    llvm/trunk/test/Transforms/LoopRotate/pr2639.ll

Added: llvm/trunk/test/Transforms/LoopRotate/pr2639.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopRotate/pr2639.ll?rev=69867&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LoopRotate/pr2639.ll (added)
+++ llvm/trunk/test/Transforms/LoopRotate/pr2639.ll Wed Apr 22 23:30:52 2009
@@ -0,0 +1,38 @@
+; RUN: llvm-as < %s | opt -loop-deletion -loop-rotate -disable-output
+; PR 2639
+
+	%struct.HexxagonMove = type { i8, i8, i32 }
+
+define void @_ZN16HexxagonMoveList7addMoveER12HexxagonMove() {
+entry:
+	br i1 false, label %bb9.preheader, label %bb11
+
+bb9.preheader:		; preds = %entry
+	br label %bb9
+
+bb1:		; preds = %bb9
+	br i1 false, label %bb3, label %bb8
+
+bb3:		; preds = %bb1
+	br label %bb5
+
+bb4:		; preds = %bb5
+	br label %bb5
+
+bb5:		; preds = %bb4, %bb3
+	%exitcond = icmp eq i32 0, 0		;  [#uses=1]
+	br i1 %exitcond, label %bb7, label %bb4
+
+bb7:		; preds = %bb5
+	store %struct.HexxagonMove* null, %struct.HexxagonMove** null, align 4
+	br label %bb8
+
+bb8:		; preds = %bb7, %bb1
+	br label %bb9
+
+bb9:		; preds = %bb8, %bb9.preheader
+	br i1 false, label %bb11, label %bb1
+
+bb11:		; preds = %bb9, %entry
+	ret void
+}




From resistor at mac.com  Wed Apr 22 23:33:42 2009
From: resistor at mac.com (Owen Anderson)
Date: Thu, 23 Apr 2009 04:33:42 -0000
Subject: [llvm-commits] [llvm] r69868 -
	/llvm/trunk/test/Analysis/ScalarEvolution/pr3909.ll
Message-ID: <200904230433.n3N4XgMd007413@zion.cs.uiuc.edu>

Author: resistor
Date: Wed Apr 22 23:33:42 2009
New Revision: 69868

URL: http://llvm.org/viewvc/llvm-project?rev=69868&view=rev
Log:
Testcase for PR3909.

Added:
    llvm/trunk/test/Analysis/ScalarEvolution/pr3909.ll

Added: llvm/trunk/test/Analysis/ScalarEvolution/pr3909.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/pr3909.ll?rev=69868&view=auto

==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/pr3909.ll (added)
+++ llvm/trunk/test/Analysis/ScalarEvolution/pr3909.ll Wed Apr 22 23:33:42 2009
@@ -0,0 +1,30 @@
+; RUN: llvm-as < %s | opt -indvars -disable-output
+; PR 3909
+
+
+	type { i32, %1* }		; type %0
+	type { i32, i8* }		; type %1
+
+define x86_stdcallcc i32 @_Dmain(%0 %unnamed) {
+entry:
+	br label %whilebody
+
+whilebody:		; preds = %endwhile5, %entry
+	%i.0 = phi i64 [ 0, %entry ], [ %tmp11, %endwhile5 ]		;  [#uses=1]
+	%m.0 = phi i64 [ 0, %entry ], [ %tmp11, %endwhile5 ]		;  [#uses=2]
+	%tmp2 = mul i64 %m.0, %m.0		;  [#uses=1]
+	br label %whilecond3
+
+whilecond3:		; preds = %whilebody4, %whilebody
+	%j.0 = phi i64 [ %tmp2, %whilebody ], [ %tmp9, %whilebody4 ]		;  [#uses=2]
+	%tmp7 = icmp ne i64 %j.0, 0		;  [#uses=1]
+	br i1 %tmp7, label %whilebody4, label %endwhile5
+
+whilebody4:		; preds = %whilecond3
+	%tmp9 = add i64 %j.0, 1		;  [#uses=1]
+	br label %whilecond3
+
+endwhile5:		; preds = %whilecond3
+	%tmp11 = add i64 %i.0, 1		;  [#uses=2]
+	br label %whilebody
+}




From nicholas at mxc.ca  Thu Apr 23 00:15:09 2009
From: nicholas at mxc.ca (Nick Lewycky)
Date: Thu, 23 Apr 2009 05:15:09 -0000
Subject: [llvm-commits] [llvm] r69870 - in /llvm/trunk:
 lib/Analysis/ScalarEvolution.cpp
 test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll
Message-ID: <200904230515.n3N5FBZC008902@zion.cs.uiuc.edu>

Author: nicholas
Date: Thu Apr 23 00:15:08 2009
New Revision: 69870

URL: http://llvm.org/viewvc/llvm-project?rev=69870&view=rev
Log:
Simplify trunc(extend(x)) in SCEVs, just for completeness. Also fix some odd
whitespace in the same file.

Added:
    llvm/trunk/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll
Modified:
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=69870&r1=69869&r2=69870&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Apr 23 00:15:08 2009
@@ -658,6 +658,14 @@
   if (SCEVTruncateExpr *ST = dyn_cast(Op))
     return getTruncateExpr(ST->getOperand(), Ty);
 
+  // trunc(sext(x)) --> sext(x) if widening or trunc(x) if narrowing
+  if (SCEVSignExtendExpr *SS = dyn_cast(Op))
+    return getTruncateOrSignExtend(SS->getOperand(), Ty);
+
+  // trunc(zext(x)) --> zext(x) if widening or trunc(x) if narrowing
+  if (SCEVZeroExtendExpr *SZ = dyn_cast(Op))
+    return getTruncateOrZeroExtend(SZ->getOperand(), Ty);
+
   // If the input value is a chrec scev made out of constants, truncate
   // all of the constants.
   if (SCEVAddRecExpr *AddRec = dyn_cast(Op)) {
@@ -1152,7 +1160,7 @@
 /// SCEVAddRecExpr::get - Get a add recurrence expression for the
 /// specified loop.  Simplify the expression as much as possible.
 SCEVHandle ScalarEvolution::getAddRecExpr(std::vector &Operands,
-                               const Loop *L) {
+                                          const Loop *L) {
   if (Operands.size() == 1) return Operands[0];
 
   if (Operands.back()->isZero()) {
@@ -1484,7 +1492,7 @@
 /// getMinusSCEV - Return a SCEV corresponding to LHS - RHS.
 ///
 SCEVHandle ScalarEvolution::getMinusSCEV(const SCEVHandle &LHS,
-                                              const SCEVHandle &RHS) {
+                                         const SCEVHandle &RHS) {
   // X - Y --> X + -Y
   return getAddExpr(LHS, getNegativeSCEV(RHS));
 }
@@ -1494,7 +1502,7 @@
 /// extended.
 SCEVHandle
 ScalarEvolution::getTruncateOrZeroExtend(const SCEVHandle &V,
-                                              const Type *Ty) {
+                                         const Type *Ty) {
   const Type *SrcTy = V->getType();
   assert((SrcTy->isInteger() || (TD && isa(SrcTy))) &&
          (Ty->isInteger() || (TD && isa(Ty))) &&
@@ -1511,7 +1519,7 @@
 /// extended.
 SCEVHandle
 ScalarEvolution::getTruncateOrSignExtend(const SCEVHandle &V,
-                                              const Type *Ty) {
+                                         const Type *Ty) {
   const Type *SrcTy = V->getType();
   assert((SrcTy->isInteger() || (TD && isa(SrcTy))) &&
          (Ty->isInteger() || (TD && isa(Ty))) &&

Added: llvm/trunk/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll?rev=69870&view=auto

==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll (added)
+++ llvm/trunk/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll Thu Apr 23 00:15:08 2009
@@ -0,0 +1,37 @@
+; RUN: llvm-as < %s | opt -analyze -scalar-evolution | grep truncate | not grep extend
+
+define i16 @test1(i8 %x) {
+  %A = sext i8 %x to i32
+  %B = trunc i32 %A to i16
+  ret i16 %B
+}
+
+define i8 @test2(i16 %x) {
+  %A = sext i16 %x to i32
+  %B = trunc i32 %A to i8
+  ret i8 %B
+}
+
+define i16 @test3(i16 %x) {
+  %A = sext i16 %x to i32
+  %B = trunc i32 %A to i16
+  ret i16 %B
+}
+
+define i16 @test4(i8 %x) {
+  %A = zext i8 %x to i32
+  %B = trunc i32 %A to i16
+  ret i16 %B
+}
+
+define i8 @test5(i16 %x) {
+  %A = zext i16 %x to i32
+  %B = trunc i32 %A to i8
+  ret i8 %B
+}
+
+define i16 @test6(i16 %x) {
+  %A = zext i16 %x to i32
+  %B = trunc i32 %A to i16
+  ret i16 %B
+}




From sanjiv.gupta at microchip.com  Thu Apr 23 00:28:28 2009
From: sanjiv.gupta at microchip.com (Sanjiv Gupta)
Date: Thu, 23 Apr 2009 10:58:28 +0530
Subject: [llvm-commits] [llvm]
	r69574	-	/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
In-Reply-To: 
References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu>	<83B4B74F-3F9C-4A66-8447-40970738F0AD@apple.com>	<49EC9FCB.7040501@microchip.com>
	
Message-ID: <49EFFC7C.2000809@microchip.com>

Dan Gohman wrote:
> On Apr 20, 2009, at 9:16 AM, Sanjiv Gupta wrote:
>
>   
>> Dan Gohman wrote:
>>     
>>> Hello,
>>>
>>> Are you planning to resubmit r58505?  It was reverted in r58547 with
>>> a message indicating that it would be resubmitted.  That patch would
>>> appear to make this r69574 unnecessary.
>>>
>>> Dan
>>>
>>>
>>>       
>> Right. Even after that this change will still hold good just in case  
>> if
>> a pointer size doesn't make valid index.
>>     
>
> If Instcombine isn't using a valid index type for this optimization
> for some target, it really should be fixed. Silently falling back to
> not doing this may just be hiding problems.
>
>   
I agree.
>> Chris had suggested that 58505 alone is not enough as the bc encoding
>> uses 1 bit to encode i32/i64 for index types.
>> He had suggested that we should be able to write i16 type indexes and
>> should be able to get back them by the command seq below.
>>  $ llvm-as < test.ll | llvm-dis | llvm-as | llvm-dis
>>
>> When I tried this with 58505, it worked.
>> So the only additional thing is that we  probably need to do the  
>> changes
>> in the documentation.
>>
>> Let me know if this understanding is incorrect. Better you can get  
>> me a
>> test case.
>>     
>
> I'm not very familiar with the bitcode encoding, but at a quick
> glance it looks like a full type is stored with each operand.
> If this just needs a documentation update, please do that and
> re-apply 58505.
>
> Thanks,
>
> D
>   
I too had similar observation last time I debugged that area.
- Sanjiv
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>   



From stoklund at 2pi.dk  Thu Apr 23 00:40:11 2009
From: stoklund at 2pi.dk (Jakob Stoklund Olesen)
Date: Thu, 23 Apr 2009 07:40:11 +0200
Subject: [llvm-commits] [PATCH] Don't -join-cross-class-copies of physical
	and virtual registers
Message-ID: <60BF6861-E1DC-4FFC-904C-E301710F4908@2pi.dk>

When SimpleRegisterCoalescing::JoinCopy is trying to coalesce a  
physical register with a virtual register, differingRegisterClasses  
returns true exactly when the physical register does not belong to the  
register class of the virtual register.

In this case it would be illegal to coalesce. The virtual register  
regclass is the set of legal registers for the instructions using it.  
A physical register outside the regclass could lead to illegal  
instruction operands.

This happens frequently when using -join-cross-class-copies with my  
Blackfin backend. It think it might not happen for X86 because the  
only instruction with particular regclass requirements is  
EXTRACT_SUBREG, and that is being removed by the coalescer.

Unfortunately I have not been able to produce an X86 test case. I have  
one for Blackfin.

The attached patch will bail out early when attempting a cross class  
join between a physical and a virtual register. It also removes a bit  
of logic that is no longer needed when both registers are known to be  
virtual.

The removed code includes the obvious typo in "if (!SrcIsPhys && ! 
SrcIsPhys)"

-------------- next part --------------
A non-text attachment was scrubbed...
Name: coalesce-phys-virt.patch
Type: application/octet-stream
Size: 3381 bytes
Desc: not available
Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090423/111f6824/attachment.obj 
-------------- next part --------------


From clattner at apple.com  Thu Apr 23 00:51:08 2009
From: clattner at apple.com (Chris Lattner)
Date: Wed, 22 Apr 2009 22:51:08 -0700
Subject: [llvm-commits] [llvm-gcc-4.2] r69795 -
	/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
In-Reply-To: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu>
References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu>
Message-ID: 


On Apr 22, 2009, at 2:28 AM, Duncan Sands wrote:

> Author: baldrick
> Date: Wed Apr 22 04:27:52 2009
> New Revision: 69795
>
> URL: http://llvm.org/viewvc/llvm-project?rev=69795&view=rev
> Log:
> Chris's new record constructor code broke the x86-32
> Ada build because it doesn't handle the case when the
> size of a field is less than the size of the type of
> the field.  Fix by truncating the initial value in this
> case.  It may be that this is only valid if the discarded
> bits are zero, but I'm not sure so I didn't add a check
> for this.

Hi Duncan,

Thanks for doing this.  Do you have a testcase?  Is this right on big- 
endian systems?

-Chris



From baldrick at free.fr  Thu Apr 23 03:03:37 2009
From: baldrick at free.fr (Duncan Sands)
Date: Thu, 23 Apr 2009 10:03:37 +0200
Subject: [llvm-commits] [llvm-gcc-4.2] r69795 -
	/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
In-Reply-To: 
References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu>
	
Message-ID: <200904231003.37841.baldrick@free.fr>

Hi Chris,

> Thanks for doing this.  Do you have a testcase?

I only have an Ada testcase, and since you can't even build
the Ada front-end without this fix it seemed rather pointless
to add it to the testsuite.

> Is this right on big-endian systems?

I think so but I'm not sure.

By the way, isn't this just the same as how C stores an
integer to a bitfield?  Suppose you have
  int x : 2;
Then when you write a value to x, what happens?  The
value is truncated down to 2 bits and those bits are
stored.  In the record constructor, each field of the
constructor is being assigned to the corresponding
bitfield.  So it seems reasonable to me to say that
integers get truncated down to the size of the bitfield
before being stored.  It's not that I like it, but it is
consistent with C bitfield assignment.

Ciao,

Duncan.


From sanjiv.gupta at microchip.com  Thu Apr 23 05:35:12 2009
From: sanjiv.gupta at microchip.com (Sanjiv Gupta)
Date: Thu, 23 Apr 2009 10:35:12 -0000
Subject: [llvm-commits] [llvm] r69883 -
	/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp
Message-ID: <200904231035.n3NAZHqV031771@zion.cs.uiuc.edu>

Author: sgupta
Date: Thu Apr 23 05:34:58 2009
New Revision: 69883

URL: http://llvm.org/viewvc/llvm-project?rev=69883&view=rev
Log:
Banksel immediate constant will always immediately follow the GA/ES, so scan an insn from beginnin to find out the banksel operand.

Modified:
    llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp

Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp?rev=69883&r1=69882&r2=69883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Thu Apr 23 05:34:58 2009
@@ -48,26 +48,28 @@
   std::string NewBank = "";
   unsigned Operands = MI->getNumOperands();
   if (Operands > 1) {
-    // Global address or external symbol should be second operand from last
-    // if we want to print banksel for it.
-    unsigned BankSelVar = Operands - 2;
-    // In cases where an instruction has a def or use defined in td file,
-    // that def or use becomes a machine instruction operand.
-    // eg. addfw_1 instruction defines STATUS register. So the machine
-    // instruction for it has MO_Register Operand as its last operand.
-    while ((MI->getOperand(BankSelVar + 1).getType() ==
-           MachineOperand::MO_Register) && (BankSelVar > 0))
-     BankSelVar--;
-    const MachineOperand &Op = MI->getOperand(BankSelVar);
-    unsigned OpType = Op.getType();
-    if (OpType == MachineOperand::MO_GlobalAddress ||
-        OpType == MachineOperand::MO_ExternalSymbol) {
+    // If we have a Global address or external symbol then we need to print 
+    // banksel for it. 
+    unsigned BankSelVar = 0;
+    MachineOperand Op = MI->getOperand(BankSelVar);
+    while (BankSelVar < Operands-1) {
+      Op = MI->getOperand(BankSelVar);
+      if ((Op.getType() ==  MachineOperand::MO_GlobalAddress) ||
+          (Op.getType() ==  MachineOperand::MO_ExternalSymbol))
+        break;
+      BankSelVar++;
+    }
+    if (BankSelVar < Operands-1) {
+      unsigned OpType = Op.getType();
       if (OpType == MachineOperand::MO_GlobalAddress ) 
         NewBank = Op.getGlobal()->getSection(); 
       else {
-        // External Symbol is generated for temp data. Temp data in in
-        // fdata..# section.
-        NewBank = "fpdata." + CurrentFnName +".#";
+        // External Symbol is generated for temp data and arguments. They are 
+        // in fpdata..# section.
+        std::string ESName = Op.getSymbolName();
+        int index = ESName.find_first_of(".");
+        std::string FnName = ESName.substr(0,index);
+        NewBank = "fpdata." + FnName +".#";
       }
       // Operand after global address or external symbol should be  banksel.
       // Value 1 for this operand means we need to generate banksel else do not
@@ -78,7 +80,7 @@
       // variables in all files are same at this time. For eg. initialized 
       // data in put in idata.# section in all files. 
       if ((BS.getType() == MachineOperand::MO_Immediate 
-           && (int)BS.getImm() == 1) 
+          && (int)BS.getImm() == 1) 
           && ((Op.isGlobal() && Op.getGlobal()->hasExternalLinkage()) ||
            (NewBank.compare(CurBank) != 0))) { 
         O << "\tbanksel ";




From gohman at apple.com  Thu Apr 23 10:16:50 2009
From: gohman at apple.com (Dan Gohman)
Date: Thu, 23 Apr 2009 15:16:50 -0000
Subject: [llvm-commits] [llvm] r69892 - in /llvm/trunk:
 include/llvm/Analysis/ScalarEvolutionExpander.h
 lib/Analysis/ScalarEvolutionExpander.cpp
 lib/Transforms/Scalar/IndVarSimplify.cpp
 test/Transforms/IndVarSimplify/casted-argument.ll
Message-ID: <200904231516.n3NFGoSg008906@zion.cs.uiuc.edu>

Author: djg
Date: Thu Apr 23 10:16:49 2009
New Revision: 69892

URL: http://llvm.org/viewvc/llvm-project?rev=69892&view=rev
Log:
Change SCEVExpander's expandCodeFor to provide more flexibility
with the persistent insertion point, and change IndVars to make
use of it. This fixes a bug where IndVars was holding on to a
stale insertion point and forcing the SCEVExpander to continue to
use it.

This fixes PR4038.

Modified:
    llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h
    llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll

Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h?rev=69892&r1=69891&r2=69892&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h Thu Apr 23 10:16:49 2009
@@ -71,13 +71,23 @@
       InsertedInstructions.insert(I);
     }
 
+    void setInsertionPoint(BasicBlock::iterator NewIP) { InsertPt = NewIP; }
+
     BasicBlock::iterator getInsertionPoint() const { return InsertPt; }
 
     /// expandCodeFor - Insert code to directly compute the specified SCEV
     /// expression into the program.  The inserted code is inserted into the
+    /// SCEVExpander's current insertion point.
+    Value *expandCodeFor(SCEVHandle SH, const Type *Ty);
+
+    /// expandCodeFor - Insert code to directly compute the specified SCEV
+    /// expression into the program.  The inserted code is inserted into the
     /// specified block.
     Value *expandCodeFor(SCEVHandle SH, const Type *Ty,
-                         BasicBlock::iterator IP);
+                         BasicBlock::iterator IP) {
+      setInsertionPoint(IP);
+      return expandCodeFor(SH, Ty);
+    }
 
     /// InsertCastOfTo - Insert a cast of V to the specified type, doing what
     /// we can to share the casts.

Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=69892&r1=69891&r2=69892&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Thu Apr 23 10:16:49 2009
@@ -332,12 +332,10 @@
   return LHS;
 }
 
-Value *SCEVExpander::expandCodeFor(SCEVHandle SH, const Type *Ty,
-                                   BasicBlock::iterator IP) {
+Value *SCEVExpander::expandCodeFor(SCEVHandle SH, const Type *Ty) {
   // Expand the code for this SCEV.
   assert(SE.getTypeSizeInBits(Ty) == SE.getTypeSizeInBits(SH->getType()) &&
          "non-trivial casts should be done with the SCEVs directly!");
-  InsertPt = IP;
   Value *V = expand(SH);
   return InsertNoopCastOfTo(V, Ty);
 }

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=69892&r1=69891&r2=69892&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Thu Apr 23 10:16:49 2009
@@ -543,8 +543,7 @@
                                       ScalarEvolution *SE,
                                       const Type *LargestType, Loop *L, 
                                       const Type *myType,
-                                      SCEVExpander &Rewriter, 
-                                      BasicBlock::iterator InsertPt) {
+                                      SCEVExpander &Rewriter) {
   SCEVHandle ExtendedStart =
     SE->getSignExtendExpr(AR->getStart(), LargestType);
   SCEVHandle ExtendedStep =
@@ -553,15 +552,14 @@
     SE->getAddRecExpr(ExtendedStart, ExtendedStep, L);
   if (LargestType != myType)
     ExtendedAddRec = SE->getTruncateExpr(ExtendedAddRec, myType);
-  return Rewriter.expandCodeFor(ExtendedAddRec, myType, InsertPt);
+  return Rewriter.expandCodeFor(ExtendedAddRec, myType);
 }
 
 static Value *getZeroExtendedTruncVar(const SCEVAddRecExpr *AR,
                                       ScalarEvolution *SE,
                                       const Type *LargestType, Loop *L, 
                                       const Type *myType,
-                                      SCEVExpander &Rewriter, 
-                                      BasicBlock::iterator InsertPt) {
+                                      SCEVExpander &Rewriter) {
   SCEVHandle ExtendedStart =
     SE->getZeroExtendExpr(AR->getStart(), LargestType);
   SCEVHandle ExtendedStep =
@@ -570,7 +568,7 @@
     SE->getAddRecExpr(ExtendedStart, ExtendedStep, L);
   if (LargestType != myType)
     ExtendedAddRec = SE->getTruncateExpr(ExtendedAddRec, myType);
-  return Rewriter.expandCodeFor(ExtendedAddRec, myType, InsertPt);
+  return Rewriter.expandCodeFor(ExtendedAddRec, myType);
 }
 
 /// allUsesAreSameTyped - See whether all Uses of I are instructions
@@ -699,6 +697,7 @@
   // recurrences in terms of the induction variable.  Start with the auxillary
   // induction variables, and recursively rewrite any of their uses.
   BasicBlock::iterator InsertPt = Header->getFirstNonPHI();
+  Rewriter.setInsertionPoint(InsertPt);
 
   // If there were induction variables of other sizes, cast the primary
   // induction variable to the right size for them, avoiding the need for the
@@ -718,7 +717,7 @@
   while (!IndVars.empty()) {
     PHINode *PN = IndVars.back().first;
     const SCEVAddRecExpr *AR = cast(IndVars.back().second);
-    Value *NewVal = Rewriter.expandCodeFor(AR, PN->getType(), InsertPt);
+    Value *NewVal = Rewriter.expandCodeFor(AR, PN->getType());
     DOUT << "INDVARS: Rewrote IV '" << *AR << "' " << *PN
          << "   into = " << *NewVal << "\n";
     NewVal->takeName(PN);
@@ -732,7 +731,7 @@
         Instruction *UInst = dyn_cast(*UI);
         if (UInst && isa(UInst) && NoSignedWrap) {
           Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType, L, 
-                                         UInst->getType(), Rewriter, InsertPt);
+                                         UInst->getType(), Rewriter);
           UInst->replaceAllUsesWith(TruncIndVar);
           DeadInsts.insert(UInst);
         }
@@ -753,8 +752,7 @@
               SExtInst* oldSext = dyn_cast(UInst->use_begin());
               uint64_t truncSize = oldSext->getType()->getPrimitiveSizeInBits();
               Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
-                                                L, oldSext->getType(), Rewriter,
-                                                InsertPt);
+                                                L, oldSext->getType(), Rewriter);
               APInt APnewAddRHS = APInt(AddRHS->getValue()).sext(newBitSize);
               if (newBitSize > truncSize)
                 APnewAddRHS = APnewAddRHS.trunc(truncSize);
@@ -784,8 +782,7 @@
             SExtInst* oldSext = dyn_cast(UInst->use_begin());
             uint64_t truncSize = oldSext->getType()->getPrimitiveSizeInBits();
             Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
-                                              L, oldSext->getType(), Rewriter,
-                                              InsertPt);
+                                              L, oldSext->getType(), Rewriter);
             APInt APnewOrRHS = APInt(RHS->getValue()).sext(newBitSize);
             if (newBitSize > truncSize)
               APnewOrRHS = APnewOrRHS.trunc(truncSize);
@@ -805,7 +802,7 @@
         // A zext of a signed variable known not to overflow is still safe.
         if (UInst && isa(UInst) && (NoUnsignedWrap || NoSignedWrap)) {
           Value *TruncIndVar = getZeroExtendedTruncVar(AR, SE, LargestType, L, 
-                                         UInst->getType(), Rewriter, InsertPt);
+                                         UInst->getType(), Rewriter);
           UInst->replaceAllUsesWith(TruncIndVar);
           DeadInsts.insert(UInst);
         }
@@ -822,7 +819,7 @@
           ZExtInst* oldZext = dyn_cast(UInst->use_begin());
           uint64_t truncSize = oldZext->getType()->getPrimitiveSizeInBits();
           Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
-                                  L, oldZext->getType(), Rewriter, InsertPt);
+                                  L, oldZext->getType(), Rewriter);
           APInt APnewAndRHS = APInt(AndRHS->getValue()).zext(newBitSize);
           if (newBitSize > truncSize)
             APnewAndRHS = APnewAndRHS.trunc(truncSize);
@@ -858,7 +855,7 @@
             ZExtInst* oldZext = dyn_cast(UInst2->use_begin());
             uint64_t truncSize = oldZext->getType()->getPrimitiveSizeInBits();
             Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
-                                    L, oldZext->getType(), Rewriter, InsertPt);
+                                    L, oldZext->getType(), Rewriter);
             ConstantInt* AndRHS = dyn_cast(UInst2->getOperand(1));
             APInt APnewAddRHS = APInt(AddRHS->getValue()).zext(newBitSize);
             if (newBitSize > truncSize)

Modified: llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll?rev=69892&r1=69891&r2=69892&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll Thu Apr 23 10:16:49 2009
@@ -1,5 +1,6 @@
 ; RUN: llvm-as < %s | opt -indvars -disable-output
 ; PR4009
+; PR4038
 
 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:32:32"
 target triple = "i386-pc-linux-gnu"
@@ -21,4 +22,27 @@
 	br label %loop
 }
 
+define void @safe_bcopy_4038(i8* %from, i8* %to, i32 %size) nounwind {
+entry:
+	br i1 false, label %if.else, label %if.then12
+
+if.then12:		; preds = %entry
+	ret void
+
+if.else:		; preds = %entry
+	%sub.ptr.rhs.cast40 = ptrtoint i8* %from to i32		;  [#uses=1]
+	br label %if.end54
+
+if.end54:		; preds = %if.end54, %if.else
+	%sub.ptr4912.pn = phi i8* [ %sub.ptr4912, %if.end54 ], [ null, %if.else ]		;  [#uses=1]
+	%sub.ptr7 = phi i8* [ %sub.ptr, %if.end54 ], [ null, %if.else ]		;  [#uses=2]
+	%sub.ptr.rhs.cast46.pn = ptrtoint i8* %from to i32		;  [#uses=1]
+	%sub.ptr.lhs.cast45.pn = ptrtoint i8* %to to i32		;  [#uses=1]
+	%sub.ptr.sub47.pn = sub i32 %sub.ptr.rhs.cast46.pn, %sub.ptr.lhs.cast45.pn		;  [#uses=1]
+	%sub.ptr4912 = getelementptr i8* %sub.ptr4912.pn, i32 %sub.ptr.sub47.pn		;  [#uses=2]
+	tail call void @bcopy(i8* %sub.ptr4912, i8* %sub.ptr7, i32 0) nounwind
+	%sub.ptr = getelementptr i8* %sub.ptr7, i32 %sub.ptr.rhs.cast40		;  [#uses=1]
+	br label %if.end54
+}
+
 declare void @bcopy(i8* nocapture) nounwind




From gohman at apple.com  Thu Apr 23 10:22:36 2009
From: gohman at apple.com (Dan Gohman)
Date: Thu, 23 Apr 2009 15:22:36 -0000
Subject: [llvm-commits] [llvm] r69893 -
	/llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll
Message-ID: <200904231522.n3NFMbLG009155@zion.cs.uiuc.edu>

Author: djg
Date: Thu Apr 23 10:22:28 2009
New Revision: 69893

URL: http://llvm.org/viewvc/llvm-project?rev=69893&view=rev
Log:
Fix an error in this test.

Modified:
    llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll

Modified: llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll?rev=69893&r1=69892&r2=69893&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll Thu Apr 23 10:22:28 2009
@@ -40,9 +40,11 @@
 	%sub.ptr.lhs.cast45.pn = ptrtoint i8* %to to i32		;  [#uses=1]
 	%sub.ptr.sub47.pn = sub i32 %sub.ptr.rhs.cast46.pn, %sub.ptr.lhs.cast45.pn		;  [#uses=1]
 	%sub.ptr4912 = getelementptr i8* %sub.ptr4912.pn, i32 %sub.ptr.sub47.pn		;  [#uses=2]
-	tail call void @bcopy(i8* %sub.ptr4912, i8* %sub.ptr7, i32 0) nounwind
+	tail call void @bcopy_4038(i8* %sub.ptr4912, i8* %sub.ptr7, i32 0) nounwind
 	%sub.ptr = getelementptr i8* %sub.ptr7, i32 %sub.ptr.rhs.cast40		;  [#uses=1]
 	br label %if.end54
 }
 
 declare void @bcopy(i8* nocapture) nounwind
+
+declare void @bcopy_4038(i8*, i32) nounwind




From sanjiv.gupta at microchip.com  Thu Apr 23 11:34:19 2009
From: sanjiv.gupta at microchip.com (Sanjiv Gupta)
Date: Thu, 23 Apr 2009 22:04:19 +0530
Subject: [llvm-commits] [llvm]
	r69574	-	/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
In-Reply-To: 
References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu>	<83B4B74F-3F9C-4A66-8447-40970738F0AD@apple.com>	<49EC9FCB.7040501@microchip.com>
	
Message-ID: <49F0988B.5040000@microchip.com>

Dan Gohman wrote:
> On Apr 20, 2009, at 9:16 AM, Sanjiv Gupta wrote:
>
>   
>> Dan Gohman wrote:
>>     
>>> Hello,
>>>
>>> Are you planning to resubmit r58505?  It was reverted in r58547 with
>>> a message indicating that it would be resubmitted.  That patch would
>>> appear to make this r69574 unnecessary.
>>>
>>> Dan
>>>
>>>
>>>       
>> Right. Even after that this change will still hold good just in case  
>> if
>> a pointer size doesn't make valid index.
>>     
>
> If Instcombine isn't using a valid index type for this optimization
> for some target, it really should be fixed. Silently falling back to
> not doing this may just be hiding problems.
>
>   
>> Chris had suggested that 58505 alone is not enough as the bc encoding
>> uses 1 bit to encode i32/i64 for index types.
>> He had suggested that we should be able to write i16 type indexes and
>> should be able to get back them by the command seq below.
>>  $ llvm-as < test.ll | llvm-dis | llvm-as | llvm-dis
>>
>> When I tried this with 58505, it worked.
>> So the only additional thing is that we  probably need to do the  
>> changes
>> in the documentation.
>>
>> Let me know if this understanding is incorrect. Better you can get  
>> me a
>> test case.
>>     
>
> I'm not very familiar with the bitcode encoding, but at a quick
> glance it looks like a full type is stored with each operand.
> If this just needs a documentation update, please do that and
> re-apply 58505.
>
> Thanks,
>
> Dan
>   
Dan,
I have worked out 58505 with the documentation and few other related 
changes.
The patches for clang and llvm are attached. Please have a look to see 
if they are good to go.

Thanks,
- Sanjiv

> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>   

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: r58505-reworked.clang.patch
Url: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090423/4e1853f6/attachment.pl 
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: r58505-reworked.patch
Url: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090423/4e1853f6/attachment-0001.pl 

From dalej at apple.com  Thu Apr 23 12:04:37 2009
From: dalej at apple.com (Dale Johannesen)
Date: Thu, 23 Apr 2009 10:04:37 -0700
Subject: [llvm-commits] [llvm-gcc-4.2] r69795 -
	/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
In-Reply-To: <200904231003.37841.baldrick@free.fr>
References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu>
	
	<200904231003.37841.baldrick@free.fr>
Message-ID: <17D0DDD6-5B1E-48FE-919D-11FB8FA93FC2@apple.com>


On Apr 23, 2009, at 1:03 AMPDT, Duncan Sands wrote:

> Hi Chris,
>
>> Thanks for doing this.  Do you have a testcase?
>
> I only have an Ada testcase, and since you can't even build
> the Ada front-end without this fix it seemed rather pointless
> to add it to the testsuite.

A C++ test affected by this bug is g++.old-deja/g++.jason/bool2.C .   
I'll put it in the llvm testsuite.



From clattner at apple.com  Thu Apr 23 12:11:00 2009
From: clattner at apple.com (Chris Lattner)
Date: Thu, 23 Apr 2009 10:11:00 -0700
Subject: [llvm-commits] [llvm-gcc-4.2] r69795 -
	/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
In-Reply-To: <200904231003.37841.baldrick@free.fr>
References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu>
	
	<200904231003.37841.baldrick@free.fr>
Message-ID: 

On Apr 23, 2009, at 1:03 AM, Duncan Sands wrote:
> Hi Chris,
>
>> Thanks for doing this.  Do you have a testcase?
>
> I only have an Ada testcase, and since you can't even build
> the Ada front-end without this fix it seemed rather pointless
> to add it to the testsuite.

Ok :)

>> Is this right on big-endian systems?
>
> I think so but I'm not sure.

You can get a reasonable amount of testing by just taking the reduced  
testcase (which just contains the global) and compiling it with a PPC- 
targetting "cc1".  It is reasonably fast to build a GCC and llvm-gcc  
cross to PPC if you don't care about anything other than cc1.  With  
that, you can just compare the .byte output from each compiler.


> By the way, isn't this just the same as how C stores an
> integer to a bitfield?  Suppose you have
>  int x : 2;
> Then when you write a value to x, what happens?

The behavior that I'm seeing is that convert to constant returns an  
"i2" value.  I assume this is because C is using TREE_PRECISION  
differently than ada?

> The
> value is truncated down to 2 bits and those bits are
> stored.  In the record constructor, each field of the
> constructor is being assigned to the corresponding
> bitfield.  So it seems reasonable to me to say that
> integers get truncated down to the size of the bitfield
> before being stored.  It's not that I like it, but it is
> consistent with C bitfield assignment.


Sure, makes sense.

-Chris


From clattner at apple.com  Thu Apr 23 12:12:11 2009
From: clattner at apple.com (Chris Lattner)
Date: Thu, 23 Apr 2009 10:12:11 -0700
Subject: [llvm-commits] [llvm-gcc-4.2] r69795 -
	/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
In-Reply-To: <17D0DDD6-5B1E-48FE-919D-11FB8FA93FC2@apple.com>
References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu>
	
	<200904231003.37841.baldrick@free.fr>
	<17D0DDD6-5B1E-48FE-919D-11FB8FA93FC2@apple.com>
Message-ID: <0D37D7F2-8DC9-42D6-B9B1-F64F9C003EEA@apple.com>


On Apr 23, 2009, at 10:04 AM, Dale Johannesen wrote:

>
> On Apr 23, 2009, at 1:03 AMPDT, Duncan Sands wrote:
>
>> Hi Chris,
>>
>>> Thanks for doing this.  Do you have a testcase?
>>
>> I only have an Ada testcase, and since you can't even build
>> the Ada front-end without this fix it seemed rather pointless
>> to add it to the testsuite.
>
> A C++ test affected by this bug is g++.old-deja/g++.jason/bool2.C .
> I'll put it in the llvm testsuite.

Ah, nice, thanks Dale!  Can you verify that the correct code is  
generated on ppc for it?

-Chris


From dalej at apple.com  Thu Apr 23 12:13:19 2009
From: dalej at apple.com (Dale Johannesen)
Date: Thu, 23 Apr 2009 10:13:19 -0700
Subject: [llvm-commits] [llvm-gcc-4.2] r69795 -
	/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
In-Reply-To: <0D37D7F2-8DC9-42D6-B9B1-F64F9C003EEA@apple.com>
References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu>
	
	<200904231003.37841.baldrick@free.fr>
	<17D0DDD6-5B1E-48FE-919D-11FB8FA93FC2@apple.com>
	<0D37D7F2-8DC9-42D6-B9B1-F64F9C003EEA@apple.com>
Message-ID: <2CE06618-690A-4842-A260-062E3DDA5518@apple.com>


On Apr 23, 2009, at 10:12 AMPDT, Chris Lattner wrote:

>
> On Apr 23, 2009, at 10:04 AM, Dale Johannesen wrote:
>
>>
>> On Apr 23, 2009, at 1:03 AMPDT, Duncan Sands wrote:
>>
>>> Hi Chris,
>>>
>>>> Thanks for doing this.  Do you have a testcase?
>>>
>>> I only have an Ada testcase, and since you can't even build
>>> the Ada front-end without this fix it seemed rather pointless
>>> to add it to the testsuite.
>>
>> A C++ test affected by this bug is g++.old-deja/g++.jason/bool2.C .
>> I'll put it in the llvm testsuite.
>
> Ah, nice, thanks Dale!  Can you verify that the correct code is
> generated on ppc for it?

OK.  I'm out of date there, will take a couple hours.



From clattner at apple.com  Thu Apr 23 12:14:55 2009
From: clattner at apple.com (Chris Lattner)
Date: Thu, 23 Apr 2009 10:14:55 -0700
Subject: [llvm-commits] [llvm-gcc-4.2] r69795 -
	/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
In-Reply-To: <2CE06618-690A-4842-A260-062E3DDA5518@apple.com>
References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu>
	
	<200904231003.37841.baldrick@free.fr>
	<17D0DDD6-5B1E-48FE-919D-11FB8FA93FC2@apple.com>
	<0D37D7F2-8DC9-42D6-B9B1-F64F9C003EEA@apple.com>
	<2CE06618-690A-4842-A260-062E3DDA5518@apple.com>
Message-ID: <27A27FFC-B023-4DC8-9170-403C3B2CC59B@apple.com>


On Apr 23, 2009, at 10:13 AM, Dale Johannesen wrote:

>>>
>>> A C++ test affected by this bug is g++.old-deja/g++.jason/bool2.C .
>>> I'll put it in the llvm testsuite.
>>
>> Ah, nice, thanks Dale!  Can you verify that the correct code is
>> generated on ppc for it?
>
> OK.  I'm out of date there, will take a couple hours.

Thanks!

-Chris


From baldrick at free.fr  Thu Apr 23 12:23:00 2009
From: baldrick at free.fr (Duncan Sands)
Date: Thu, 23 Apr 2009 19:23:00 +0200
Subject: [llvm-commits] [llvm-gcc-4.2] r69795 -
	/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
In-Reply-To: 
References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu>
	<200904231003.37841.baldrick@free.fr>
	
Message-ID: <200904231923.01217.baldrick@free.fr>

> You can get a reasonable amount of testing by just taking the reduced  
> testcase (which just contains the global) and compiling it with a PPC- 
> targetting "cc1".  It is reasonably fast to build a GCC and llvm-gcc  
> cross to PPC if you don't care about anything other than cc1.  With  
> that, you can just compare the .byte output from each compiler.

Not sure how cc1 is relevant to an Ada testcase :)
Anyway, Dale seems to have found a nice C++ testcase,
so as punishment for his good work I'll let him check
PPC!

Ciao,

Duncan.


From dalej at apple.com  Thu Apr 23 13:04:04 2009
From: dalej at apple.com (Dale Johannesen)
Date: Thu, 23 Apr 2009 18:04:04 -0000
Subject: [llvm-commits] [llvm] r69901 -
	/llvm/trunk/test/FrontendC++/2009-04-23-bool2.cpp
Message-ID: <200904231804.n3NI44lA014367@zion.cs.uiuc.edu>

Author: johannes
Date: Thu Apr 23 13:04:04 2009
New Revision: 69901

URL: http://llvm.org/viewvc/llvm-project?rev=69901&view=rev
Log:
Testcase for 69795.


Added:
    llvm/trunk/test/FrontendC++/2009-04-23-bool2.cpp

Added: llvm/trunk/test/FrontendC++/2009-04-23-bool2.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC%2B%2B/2009-04-23-bool2.cpp?rev=69901&view=auto

==============================================================================
--- llvm/trunk/test/FrontendC++/2009-04-23-bool2.cpp (added)
+++ llvm/trunk/test/FrontendC++/2009-04-23-bool2.cpp Thu Apr 23 13:04:04 2009
@@ -0,0 +1,15 @@
+// RUN: %llvmgxx -c -emit-llvm %s -o /dev/null
+// g++.old-deja/g++.jason/bool2.C from gcc testsuite.
+// Crashed before 67975 went in.
+struct F {
+  bool b1 : 1;
+  bool b2 : 7;
+};
+
+int main()
+{
+  F f = { true, true };
+
+  if (int (f.b1) != 1)
+    return 1;
+}




From isanbard at gmail.com  Thu Apr 23 13:13:05 2009
From: isanbard at gmail.com (Bill Wendling)
Date: Thu, 23 Apr 2009 11:13:05 -0700
Subject: [llvm-commits] [llvm] r69868 -
	/llvm/trunk/test/Analysis/ScalarEvolution/pr3909.ll
In-Reply-To: <200904230433.n3N4XgMd007413@zion.cs.uiuc.edu>
References: <200904230433.n3N4XgMd007413@zion.cs.uiuc.edu>
Message-ID: <16e5fdf90904231113n3dda5984ld7a3723439f257d3@mail.gmail.com>

On Wed, Apr 22, 2009 at 9:33 PM, Owen Anderson  wrote:
> Author: resistor
> Date: Wed Apr 22 23:33:42 2009
> New Revision: 69868
>
> URL: http://llvm.org/viewvc/llvm-project?rev=69868&view=rev
> Log:
> Testcase for PR3909.
>
Thanks, Owen!

-bw


From jyasskin at google.com  Thu Apr 23 13:57:34 2009
From: jyasskin at google.com (Jeffrey Yasskin)
Date: Thu, 23 Apr 2009 11:57:34 -0700
Subject: [llvm-commits] ONLY_TOOLS make variable to specify tools to build
	from the command line
Message-ID: 

Here's the patch I was talking about on the IRC channel, to let me
build fewer tools without hacking the Makefile.

Jeffrey
-------------- next part --------------
A non-text attachment was scrubbed...
Name: only_tools.patch
Type: application/octet-stream
Size: 2206 bytes
Desc: not available
Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090423/770feab6/attachment.obj 

From kremenek at apple.com  Thu Apr 23 14:11:58 2009
From: kremenek at apple.com (Ted Kremenek)
Date: Thu, 23 Apr 2009 19:11:58 -0000
Subject: [llvm-commits] [llvm] r69909 - /llvm/tags/checker/checker-0.188/
Message-ID: <200904231911.n3NJBwoV016918@zion.cs.uiuc.edu>

Author: kremenek
Date: Thu Apr 23 14:11:58 2009
New Revision: 69909

URL: http://llvm.org/viewvc/llvm-project?rev=69909&view=rev
Log:
Tagging checker-0.188.

Added:
    llvm/tags/checker/checker-0.188/
      - copied from r69908, llvm/trunk/



From gohman at apple.com  Thu Apr 23 14:39:42 2009
From: gohman at apple.com (Dan Gohman)
Date: Thu, 23 Apr 2009 19:39:42 -0000
Subject: [llvm-commits] [llvm] r69911 - in /llvm/trunk/test/CodeGen/X86:
 critical-edge-split.ll fastcc-byval.ll fastcc-sret.ll
Message-ID: <200904231939.n3NJdgmZ017675@zion.cs.uiuc.edu>

Author: djg
Date: Thu Apr 23 14:39:41 2009
New Revision: 69911

URL: http://llvm.org/viewvc/llvm-project?rev=69911&view=rev
Log:
Explicitly pass -tailcallopt=false to these tests so that they
work as intended no matter what the default setting of that
option is.

Modified:
    llvm/trunk/test/CodeGen/X86/critical-edge-split.ll
    llvm/trunk/test/CodeGen/X86/fastcc-byval.ll
    llvm/trunk/test/CodeGen/X86/fastcc-sret.ll

Modified: llvm/trunk/test/CodeGen/X86/critical-edge-split.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/critical-edge-split.ll?rev=69911&r1=69910&r2=69911&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/X86/critical-edge-split.ll (original)
+++ llvm/trunk/test/CodeGen/X86/critical-edge-split.ll Thu Apr 23 14:39:41 2009
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -stats -info-output-file - | grep asm-printer | grep 31
+; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -tailcallopt=false -stats -info-output-file - | grep asm-printer | grep 31
 
 	%CC = type { %Register }
 	%II = type { %"struct.XX::II::$_74" }

Modified: llvm/trunk/test/CodeGen/X86/fastcc-byval.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fastcc-byval.ll?rev=69911&r1=69910&r2=69911&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/X86/fastcc-byval.ll (original)
+++ llvm/trunk/test/CodeGen/X86/fastcc-byval.ll Thu Apr 23 14:39:41 2009
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc | grep {movl\[\[:space:\]\]*8(%esp), %eax} | count 2
+; RUN: llvm-as < %s | llc -tailcallopt=false | grep {movl\[\[:space:\]\]*8(%esp), %eax} | count 2
 ; PR3122
 ; rdar://6400815
 

Modified: llvm/trunk/test/CodeGen/X86/fastcc-sret.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fastcc-sret.ll?rev=69911&r1=69910&r2=69911&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/X86/fastcc-sret.ll (original)
+++ llvm/trunk/test/CodeGen/X86/fastcc-sret.ll Thu Apr 23 14:39:41 2009
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc -march=x86 | grep ret | not grep 4
+; RUN: llvm-as < %s | llc -march=x86 -tailcallopt=false | grep ret | not grep 4
 
 	%struct.foo = type { [4 x i32] }
 




From kremenek at apple.com  Thu Apr 23 14:52:42 2009
From: kremenek at apple.com (Ted Kremenek)
Date: Thu, 23 Apr 2009 19:52:42 -0000
Subject: [llvm-commits] [llvm] r69912 - /llvm/tags/checker/checker-0.188/
Message-ID: <200904231952.n3NJqgeR018151@zion.cs.uiuc.edu>

Author: kremenek
Date: Thu Apr 23 14:52:40 2009
New Revision: 69912

URL: http://llvm.org/viewvc/llvm-project?rev=69912&view=rev
Log:
Removing checker-0.188.

Removed:
    llvm/tags/checker/checker-0.188/



From evan.cheng at apple.com  Thu Apr 23 15:18:13 2009
From: evan.cheng at apple.com (Evan Cheng)
Date: Thu, 23 Apr 2009 20:18:13 -0000
Subject: [llvm-commits] [llvm] r69918 -
	/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp
Message-ID: <200904232018.n3NKIDs3019171@zion.cs.uiuc.edu>

Author: evancheng
Date: Thu Apr 23 15:18:13 2009
New Revision: 69918

URL: http://llvm.org/viewvc/llvm-project?rev=69918&view=rev
Log:
Fix an obvious type.

Modified:
    llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp

Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp?rev=69918&r1=69917&r2=69918&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp (original)
+++ llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Thu Apr 23 15:18:13 2009
@@ -1342,7 +1342,7 @@
         return false;
       }
       Limit = allocatableRCRegs_[DstRC].count();
-    } else if (!SrcIsPhys && !SrcIsPhys) {
+    } else if (!SrcIsPhys && !DstIsPhys) {
       unsigned SrcSize = SrcRC->getSize();
       unsigned DstSize = DstRC->getSize();
       if (SrcSize < DstSize)




From evan.cheng at apple.com  Thu Apr 23 15:39:31 2009
From: evan.cheng at apple.com (Evan Cheng)
Date: Thu, 23 Apr 2009 20:39:31 -0000
Subject: [llvm-commits] [llvm] r69919 -
	/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp
Message-ID: <200904232039.n3NKdVsS019939@zion.cs.uiuc.edu>

Author: evancheng
Date: Thu Apr 23 15:39:31 2009
New Revision: 69919

URL: http://llvm.org/viewvc/llvm-project?rev=69919&view=rev
Log:
Update comments.

Modified:
    llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp

Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp?rev=69919&r1=69918&r2=69919&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp (original)
+++ llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Thu Apr 23 15:39:31 2009
@@ -1305,7 +1305,7 @@
         // FIXME: can we handle this?
         return false;
       // This is not an insert_subreg but it looks like one.
-      // e.g. %reg1024:3 = MOV32rr %EAX
+      // e.g. %reg1024:4 = MOV32rr %EAX
       isInsSubReg = true;
       if (SrcIsPhys) {
         if (!CanJoinInsertSubRegToPhysReg(DstReg, SrcReg, SubIdx, RealSrcReg))
@@ -1316,7 +1316,7 @@
       SubIdx = SrcMO->getSubReg();
       if (SubIdx) {
         // This is not a extract_subreg but it looks like one.
-        // e.g. %cl = MOV16rr %reg1024:2
+        // e.g. %cl = MOV16rr %reg1024:1
         isExtSubReg = true;
         if (DstIsPhys) {
           if (!CanJoinExtractSubRegToPhysReg(DstReg, SrcReg, SubIdx,RealDstReg))




From evan.cheng at apple.com  Thu Apr 23 15:40:57 2009
From: evan.cheng at apple.com (Evan Cheng)
Date: Thu, 23 Apr 2009 13:40:57 -0700
Subject: [llvm-commits] [PATCH] Don't -join-cross-class-copies of
	physical	and virtual registers
In-Reply-To: <60BF6861-E1DC-4FFC-904C-E301710F4908@2pi.dk>
References: <60BF6861-E1DC-4FFC-904C-E301710F4908@2pi.dk>
Message-ID: <22FEC6A4-57A8-44E5-8844-79E3056D8A13@apple.com>

Unfortunately your patch will disable some of the functionalities for  
X86. See the comments:

       // This is not an insert_subreg but it looks like one.
       // e.g. %reg1024:4 = MOV32rr %EAX

That means reg1024 is a 64-bit register. EAX is not in the register  
class but we want to coalesce this by assigning RAX to reg1024.

Can you find another solution?

Evan
On Apr 22, 2009, at 10:40 PM, Jakob Stoklund Olesen wrote:

> When SimpleRegisterCoalescing::JoinCopy is trying to coalesce a  
> physical register with a virtual register, differingRegisterClasses  
> returns true exactly when the physical register does not belong to  
> the register class of the virtual register.
>
> In this case it would be illegal to coalesce. The virtual register  
> regclass is the set of legal registers for the instructions using  
> it. A physical register outside the regclass could lead to illegal  
> instruction operands.
>
> This happens frequently when using -join-cross-class-copies with my  
> Blackfin backend. It think it might not happen for X86 because the  
> only instruction with particular regclass requirements is  
> EXTRACT_SUBREG, and that is being removed by the coalescer.
>
> Unfortunately I have not been able to produce an X86 test case. I  
> have one for Blackfin.
>
> The attached patch will bail out early when attempting a cross class  
> join between a physical and a virtual register. It also removes a  
> bit of logic that is no longer needed when both registers are known  
> to be virtual.
>
> The removed code includes the obvious typo in "if (!SrcIsPhys && ! 
> SrcIsPhys)"
>
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



From greened at obbligato.org  Thu Apr 23 16:25:16 2009
From: greened at obbligato.org (David Greene)
Date: Thu, 23 Apr 2009 21:25:16 -0000
Subject: [llvm-commits] [llvm] r69921 - in /llvm/trunk:
 docs/TableGenFundamentals.html test/TableGen/nameconcat.td
 utils/TableGen/CodeGenInstruction.cpp utils/TableGen/Record.cpp
 utils/TableGen/Record.h utils/TableGen/TGParser.cpp
Message-ID: <200904232125.n3NLPGmY021595@zion.cs.uiuc.edu>

Author: greened
Date: Thu Apr 23 16:25:15 2009
New Revision: 69921

URL: http://llvm.org/viewvc/llvm-project?rev=69921&view=rev
Log:

Make BinOps typed and require a type specifier for !nameconcat.  This
allows binops to be used in typed contexts such as when passing
arguments to classes.

Modified:
    llvm/trunk/docs/TableGenFundamentals.html
    llvm/trunk/test/TableGen/nameconcat.td
    llvm/trunk/utils/TableGen/CodeGenInstruction.cpp
    llvm/trunk/utils/TableGen/Record.cpp
    llvm/trunk/utils/TableGen/Record.h
    llvm/trunk/utils/TableGen/TGParser.cpp

Modified: llvm/trunk/docs/TableGenFundamentals.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGenFundamentals.html?rev=69921&r1=69920&r2=69921&view=diff

==============================================================================
--- llvm/trunk/docs/TableGenFundamentals.html (original)
+++ llvm/trunk/docs/TableGenFundamentals.html Thu Apr 23 16:25:15 2009
@@ -398,11 +398,11 @@
 
!strconcat(a, b)
A string value that is the result of concatenating the 'a' and 'b' strings.
-
!nameconcat(a, b)
+
!nameconcat(a, b)
A value that is the result of concatenating the 'a' and 'b' strings and looking up the resulting name in the symbol table. The symbol type - determines the type of the resulting value. If the symbol is not found, - TableGen emits an error and aborts.
+ determines the type of the resulting value. If the symbol is not found + or the symbol type does not match 'type,' TableGen emits an error and aborts.

Note that all of the values have rules specifying how they convert to values Modified: llvm/trunk/test/TableGen/nameconcat.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/nameconcat.td?rev=69921&r1=69920&r2=69921&view=diff ============================================================================== --- llvm/trunk/test/TableGen/nameconcat.td (original) +++ llvm/trunk/test/TableGen/nameconcat.td Thu Apr 23 16:25:15 2009 @@ -1,4 +1,4 @@ -// RUN: tblgen %s | grep {add_ps} | count 2 +// RUN: tblgen %s | grep {add_ps} | count 3 class ValueType { int Size = size; @@ -66,11 +66,25 @@ multiclass arith opcode, string asmstr, string Intr> { def PS : Inst; + [(set VR128:$dst, (!nameconcat(Intr, "_ps") VR128:$src1, VR128:$src2))]>; def PD : Inst; + [(set VR128:$dst, (!nameconcat(Intr, "_pd") VR128:$src1, VR128:$src2))]>; } defm ADD : arith<0x58, "add", "int_x86_sse2_add">; + +class IntInst opcode, string asmstr, Intrinsic Intr> : + Inst; + + +multiclass arith_int opcode, string asmstr, string Intr> { + def PS_Int : IntInst(Intr, "_ps")>; + + def PD_Int : IntInst(Intr, "_pd")>; +} + +defm ADD : arith_int<0x58, "add", "int_x86_sse2_add">; Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.cpp?rev=69921&r1=69920&r2=69921&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenInstruction.cpp (original) +++ llvm/trunk/utils/TableGen/CodeGenInstruction.cpp Thu Apr 23 16:25:15 2009 @@ -127,7 +127,7 @@ OperandList.clear(); return; } - DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold(R, 0); + DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI, new DagRecTy))->Fold(R, 0); unsigned MIOperandNo = 0; std::set OperandNames; Modified: llvm/trunk/utils/TableGen/Record.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.cpp?rev=69921&r1=69920&r2=69921&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/Record.cpp (original) +++ llvm/trunk/utils/TableGen/Record.cpp Thu Apr 23 16:25:15 2009 @@ -138,10 +138,21 @@ Init *R = BO->getRHS()->convertInitializerTo(this); if (L == 0 || R == 0) return 0; if (L != BO->getLHS() || R != BO->getRHS()) - return new BinOpInit(BinOpInit::STRCONCAT, L, R); + return new BinOpInit(BinOpInit::STRCONCAT, L, R, new StringRecTy); return BO; } - return 0; + if (BO->getOpcode() == BinOpInit::NAMECONCAT) { + if (BO->getType()->getAsString() == getAsString()) { + Init *L = BO->getLHS()->convertInitializerTo(this); + Init *R = BO->getRHS()->convertInitializerTo(this); + if (L == 0 || R == 0) return 0; + if (L != BO->getLHS() || R != BO->getRHS()) + return new BinOpInit(BinOpInit::NAMECONCAT, L, R, new StringRecTy); + return BO; + } + } + + return convertValue((TypedInit*)BO); } @@ -195,9 +206,19 @@ Init *R = BO->getRHS()->convertInitializerTo(this); if (L == 0 || R == 0) return 0; if (L != BO->getLHS() || R != BO->getRHS()) - return new BinOpInit(BinOpInit::CONCAT, L, R); + return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy); return BO; } + if (BO->getOpcode() == BinOpInit::NAMECONCAT) { + if (BO->getType()->getAsString() == getAsString()) { + Init *L = BO->getLHS()->convertInitializerTo(this); + Init *R = BO->getRHS()->convertInitializerTo(this); + if (L == 0 || R == 0) return 0; + if (L != BO->getLHS() || R != BO->getRHS()) + return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy); + return BO; + } + } return 0; } @@ -445,13 +466,22 @@ // From TGParser::ParseIDValue if (CurRec) { - if (const RecordVal *RV = CurRec->getValue(Name)) + if (const RecordVal *RV = CurRec->getValue(Name)) { + if (RV->getType() != getType()) { + throw "type mismatch in nameconcat"; + } return new VarInit(Name, RV->getType()); - + } + std::string TemplateArgName = CurRec->getName()+":"+Name; if (CurRec->isTemplateArg(TemplateArgName)) { const RecordVal *RV = CurRec->getValue(TemplateArgName); assert(RV && "Template arg doesn't exist??"); + + if (RV->getType() != getType()) { + throw "type mismatch in nameconcat"; + } + return new VarInit(TemplateArgName, RV->getType()); } } @@ -461,6 +491,11 @@ if (CurMultiClass->Rec.isTemplateArg(MCName)) { const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); assert(RV && "Template arg doesn't exist??"); + + if (RV->getType() != getType()) { + throw "type mismatch in nameconcat"; + } + return new VarInit(MCName, RV->getType()); } } @@ -501,7 +536,7 @@ Init *rhs = RHS->resolveReferences(R, RV); if (LHS != lhs || RHS != rhs) - return (new BinOpInit(getOpcode(), lhs, rhs))->Fold(&R, 0); + return (new BinOpInit(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0); return Fold(&R, 0); } @@ -513,11 +548,40 @@ case SRA: Result = "!sra"; break; case SRL: Result = "!srl"; break; case STRCONCAT: Result = "!strconcat"; break; - case NAMECONCAT: Result = "!nameconcat"; break; + case NAMECONCAT: + Result = "!nameconcat<" + getType()->getAsString() + ">"; break; } return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; } +Init *BinOpInit::resolveBitReference(Record &R, const RecordVal *IRV, + unsigned Bit) { + Init *Folded = Fold(&R, 0); + + if (Folded != this) { + TypedInit *Typed = dynamic_cast(Folded); + if (Typed) { + return Typed->resolveBitReference(R, IRV, Bit); + } + } + + return 0; +} + +Init *BinOpInit::resolveListElementReference(Record &R, const RecordVal *IRV, + unsigned Elt) { + Init *Folded = Fold(&R, 0); + + if (Folded != this) { + TypedInit *Typed = dynamic_cast(Folded); + if (Typed) { + return Typed->resolveListElementReference(R, IRV, Elt); + } + } + + return 0; +} + Init *TypedInit::convertInitializerBitRange(const std::vector &Bits) { BitsRecTy *T = dynamic_cast(getType()); if (T == 0) return 0; // Cannot subscript a non-bits variable... Modified: llvm/trunk/utils/TableGen/Record.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.h?rev=69921&r1=69920&r2=69921&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/Record.h (original) +++ llvm/trunk/utils/TableGen/Record.h Thu Apr 23 16:25:15 2009 @@ -77,7 +77,9 @@ virtual Init *convertValue( IntInit *II) { return 0; } virtual Init *convertValue(StringInit *SI) { return 0; } virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( BinOpInit *UI) { return 0; } + virtual Init *convertValue( BinOpInit *UI) { + return convertValue((TypedInit*)UI); + } virtual Init *convertValue( CodeInit *CI) { return 0; } virtual Init *convertValue(VarBitInit *VB) { return 0; } virtual Init *convertValue( DefInit *DI) { return 0; } @@ -123,7 +125,7 @@ virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; } virtual Init *convertValue( DefInit *DI) { return 0; } virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( BinOpInit *UI) { return 0; } + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} virtual Init *convertValue( TypedInit *TI); virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} @@ -165,7 +167,7 @@ virtual Init *convertValue(VarBitInit *VB) { return 0; } virtual Init *convertValue( DefInit *DI) { return 0; } virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( BinOpInit *UI) { return 0; } + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} virtual Init *convertValue( TypedInit *TI); virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} @@ -203,7 +205,7 @@ virtual Init *convertValue(VarBitInit *VB) { return 0; } virtual Init *convertValue( DefInit *DI) { return 0; } virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( BinOpInit *UI) { return 0; } + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} virtual Init *convertValue( TypedInit *TI); virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} @@ -282,7 +284,7 @@ virtual Init *convertValue(VarBitInit *VB) { return 0; } virtual Init *convertValue( DefInit *DI) { return 0; } virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( BinOpInit *UI) { return 0; } + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} virtual Init *convertValue( TypedInit *TI); virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} @@ -319,7 +321,7 @@ virtual Init *convertValue(VarBitInit *VB) { return 0; } virtual Init *convertValue( DefInit *DI) { return 0; } virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( BinOpInit *UI) { return 0; } + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} virtual Init *convertValue( TypedInit *TI); virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} @@ -393,7 +395,7 @@ virtual Init *convertValue( ListInit *LI) { return 0; } virtual Init *convertValue( CodeInit *CI) { return 0; } virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( BinOpInit *UI) { return 0; } + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} virtual Init *convertValue( DefInit *DI); virtual Init *convertValue( DagInit *DI) { return 0; } virtual Init *convertValue( TypedInit *VI); @@ -656,36 +658,6 @@ inline bool empty() const { return Values.empty(); } }; -/// BinOpInit - !op (X, Y) - Combine two inits. -/// -class BinOpInit : public Init { -public: - enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, NAMECONCAT }; -private: - BinaryOp Opc; - Init *LHS, *RHS; -public: - BinOpInit(BinaryOp opc, Init *lhs, Init *rhs) : Opc(opc), LHS(lhs), RHS(rhs) { - } - - BinaryOp getOpcode() const { return Opc; } - Init *getLHS() const { return LHS; } - Init *getRHS() const { return RHS; } - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass); - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - virtual Init *resolveReferences(Record &R, const RecordVal *RV); - - virtual std::string getAsString() const; -}; - - /// TypedInit - This is the common super-class of types that have a specific, /// explicit, type. @@ -714,6 +686,43 @@ unsigned Elt) = 0; }; + +/// BinOpInit - !op (X, Y) - Combine two inits. +/// +class BinOpInit : public TypedInit { +public: + enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, NAMECONCAT }; +private: + BinaryOp Opc; + Init *LHS, *RHS; +public: + BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) : + TypedInit(Type), Opc(opc), LHS(lhs), RHS(rhs) { + } + + BinaryOp getOpcode() const { return Opc; } + Init *getLHS() const { return LHS; } + Init *getRHS() const { return RHS; } + + // Fold - If possible, fold this to a simpler init. Return this if not + // possible to fold. + Init *Fold(Record *CurRec, MultiClass *CurMultiClass); + + virtual Init *convertInitializerTo(RecTy *Ty) { + return Ty->convertValue(this); + } + + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit); + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt); + + virtual Init *resolveReferences(Record &R, const RecordVal *RV); + + virtual std::string getAsString() const; +}; + + /// VarInit - 'Opcode' - Represent a reference to an entire variable object. /// class VarInit : public TypedInit { Modified: llvm/trunk/utils/TableGen/TGParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.cpp?rev=69921&r1=69920&r2=69921&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/TGParser.cpp (original) +++ llvm/trunk/utils/TableGen/TGParser.cpp Thu Apr 23 16:25:15 2009 @@ -784,6 +784,26 @@ BinOpInit::BinaryOp Code = BinOpInit::NAMECONCAT; Lex.Lex(); // eat the operation + + if (Lex.getCode() != tgtok::less) { + TokError("expected type name for nameconcat"); + return 0; + } + Lex.Lex(); // eat the < + + RecTy *Type = ParseType(); + + if (Type == 0) { + TokError("expected type name for nameconcat"); + return 0; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected type name for nameconcat"); + return 0; + } + Lex.Lex(); // eat the > + if (Lex.getCode() != tgtok::l_paren) { TokError("expected '(' after binary operator"); return 0; @@ -807,7 +827,7 @@ return 0; } Lex.Lex(); // eat the ')' - Operator = (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass); + Operator = (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass); } // If the operator name is present, parse it. @@ -842,16 +862,59 @@ case tgtok::XStrConcat: case tgtok::XNameConcat: { // Value ::= !binop '(' Value ',' Value ')' BinOpInit::BinaryOp Code; + RecTy *Type = 0; + + switch (Lex.getCode()) { default: assert(0 && "Unhandled code!"); - case tgtok::XConcat: Code = BinOpInit::CONCAT; break; - case tgtok::XSRA: Code = BinOpInit::SRA; break; - case tgtok::XSRL: Code = BinOpInit::SRL; break; - case tgtok::XSHL: Code = BinOpInit::SHL; break; - case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break; - case tgtok::XNameConcat: Code = BinOpInit::NAMECONCAT; break; + case tgtok::XConcat: + Lex.Lex(); // eat the operation + Code = BinOpInit::CONCAT; + Type = new DagRecTy(); + break; + case tgtok::XSRA: + Lex.Lex(); // eat the operation + Code = BinOpInit::SRA; + Type = new IntRecTy(); + break; + case tgtok::XSRL: + Lex.Lex(); // eat the operation + Code = BinOpInit::SRL; + Type = new IntRecTy(); + break; + case tgtok::XSHL: + Lex.Lex(); // eat the operation + Code = BinOpInit::SHL; + Type = new IntRecTy(); + break; + case tgtok::XStrConcat: + Lex.Lex(); // eat the operation + Code = BinOpInit::STRCONCAT; + Type = new StringRecTy(); + break; + case tgtok::XNameConcat: + Lex.Lex(); // eat the operation + Code = BinOpInit::NAMECONCAT; + if (Lex.getCode() != tgtok::less) { + TokError("expected type name for nameconcat"); + return 0; + } + Lex.Lex(); // eat the < + + Type = ParseType(); + + if (Type == 0) { + TokError("expected type name for nameconcat"); + return 0; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected type name for nameconcat"); + return 0; + } + Lex.Lex(); // eat the > + break; } - Lex.Lex(); // eat the operation if (Lex.getCode() != tgtok::l_paren) { TokError("expected '(' after binary operator"); return 0; @@ -875,7 +938,7 @@ return 0; } Lex.Lex(); // eat the ')' - return (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass); + return (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass); } } From greened at obbligato.org Thu Apr 23 16:27:59 2009 From: greened at obbligato.org (David Greene) Date: Thu, 23 Apr 2009 21:27:59 -0000 Subject: [llvm-commits] [llvm] r69923 - /llvm/trunk/docs/TableGenFundamentals.html Message-ID: <200904232127.n3NLRxbL021917@zion.cs.uiuc.edu> Author: greened Date: Thu Apr 23 16:27:58 2009 New Revision: 69923 URL: http://llvm.org/viewvc/llvm-project?rev=69923&view=rev Log: Fix a documentation bug. Modified: llvm/trunk/docs/TableGenFundamentals.html Modified: llvm/trunk/docs/TableGenFundamentals.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGenFundamentals.html?rev=69923&r1=69922&r2=69923&view=diff ============================================================================== --- llvm/trunk/docs/TableGenFundamentals.html (original) +++ llvm/trunk/docs/TableGenFundamentals.html Thu Apr 23 16:27:58 2009 @@ -398,7 +398,7 @@

!strconcat(a, b)
A string value that is the result of concatenating the 'a' and 'b' strings.
-
!nameconcat(a, b)
+
!nameconcat<type>(a, b)
A value that is the result of concatenating the 'a' and 'b' strings and looking up the resulting name in the symbol table. The symbol type determines the type of the resulting value. If the symbol is not found From kremenek at apple.com Thu Apr 23 16:28:05 2009 From: kremenek at apple.com (Ted Kremenek) Date: Thu, 23 Apr 2009 21:28:05 -0000 Subject: [llvm-commits] [llvm] r69924 - /llvm/tags/checker/checker-0.188/ Message-ID: <200904232128.n3NLS5Qp021930@zion.cs.uiuc.edu> Author: kremenek Date: Thu Apr 23 16:28:05 2009 New Revision: 69924 URL: http://llvm.org/viewvc/llvm-project?rev=69924&view=rev Log: Tagging checker-0.188. Added: llvm/tags/checker/checker-0.188/ - copied from r69923, llvm/trunk/ From kremenek at apple.com Thu Apr 23 16:48:26 2009 From: kremenek at apple.com (Ted Kremenek) Date: Thu, 23 Apr 2009 21:48:26 -0000 Subject: [llvm-commits] [llvm] r69926 - /llvm/tags/checker/checker-0.188/ Message-ID: <200904232148.n3NLmQKS022854@zion.cs.uiuc.edu> Author: kremenek Date: Thu Apr 23 16:48:24 2009 New Revision: 69926 URL: http://llvm.org/viewvc/llvm-project?rev=69926&view=rev Log: Removing checker-0.188. Removed: llvm/tags/checker/checker-0.188/ From kremenek at apple.com Thu Apr 23 17:11:31 2009 From: kremenek at apple.com (Ted Kremenek) Date: Thu, 23 Apr 2009 22:11:31 -0000 Subject: [llvm-commits] [llvm] r69930 - /llvm/tags/checker/checker-0.188/ Message-ID: <200904232211.n3NMBV2Y023840@zion.cs.uiuc.edu> Author: kremenek Date: Thu Apr 23 17:11:30 2009 New Revision: 69930 URL: http://llvm.org/viewvc/llvm-project?rev=69930&view=rev Log: Tagging checker-0.188. Added: llvm/tags/checker/checker-0.188/ - copied from r69929, llvm/trunk/ From gohman at apple.com Thu Apr 23 17:41:05 2009 From: gohman at apple.com (Dan Gohman) Date: Thu, 23 Apr 2009 22:41:05 -0000 Subject: [llvm-commits] [llvm] r69934 - /llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h Message-ID: <200904232241.n3NMf6RO024896@zion.cs.uiuc.edu> Author: djg Date: Thu Apr 23 17:41:05 2009 New Revision: 69934 URL: http://llvm.org/viewvc/llvm-project?rev=69934&view=rev Log: Fix spurious indentation in a comment. Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h?rev=69934&r1=69933&r2=69934&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h (original) +++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h Thu Apr 23 17:41:05 2009 @@ -326,7 +326,7 @@ /// the offset of the target addressing mode. virtual bool isLegalAddressImmediate(GlobalValue *GV) const; - /// IsEligibleForTailCallOptimization - Check whether the call is eligible + /// IsEligibleForTailCallOptimization - Check whether the call is eligible /// for tail call optimization. Target which want to do tail call /// optimization should implement this function. virtual bool IsEligibleForTailCallOptimization(CallSDNode *TheCall, From gohman at apple.com Thu Apr 23 17:50:03 2009 From: gohman at apple.com (Dan Gohman) Date: Thu, 23 Apr 2009 22:50:03 -0000 Subject: [llvm-commits] [llvm] r69935 - /llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Message-ID: <200904232250.n3NMo3fh025247@zion.cs.uiuc.edu> Author: djg Date: Thu Apr 23 17:50:03 2009 New Revision: 69935 URL: http://llvm.org/viewvc/llvm-project?rev=69935&view=rev Log: Handle Void types in ComputeValueVTs. This doesn't currently occur, but this change makes the code more general and easier to adapt for new purposes. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp?rev=69935&r1=69934&r2=69935&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Thu Apr 23 17:50:03 2009 @@ -135,6 +135,9 @@ StartingOffset + i * EltSize); return; } + // Interpret void as zero return values. + if (Ty == Type::VoidTy) + return; // Base case: we can get an MVT for this LLVM IR type. ValueVTs.push_back(TLI.getValueType(Ty)); if (Offsets) From gohman at apple.com Thu Apr 23 18:13:24 2009 From: gohman at apple.com (Dan Gohman) Date: Thu, 23 Apr 2009 23:13:24 -0000 Subject: [llvm-commits] [llvm] r69937 - in /llvm/trunk/lib/CodeGen/SelectionDAG: SelectionDAGBuild.cpp SelectionDAGBuild.h SelectionDAGISel.cpp Message-ID: <200904232313.n3NNDPVc025921@zion.cs.uiuc.edu> Author: djg Date: Thu Apr 23 18:13:24 2009 New Revision: 69937 URL: http://llvm.org/viewvc/llvm-project?rev=69937&view=rev Log: Factor out a bit of code that appears in several places into a utility function. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp?rev=69937&r1=69936&r2=69937&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Thu Apr 23 18:13:24 2009 @@ -1020,6 +1020,17 @@ &NewValues[0], NewValues.size())); } +/// CopyToExportRegsIfNeeded - If the given value has virtual registers +/// created for it, emit nodes to copy the value into the virtual +/// registers. +void SelectionDAGLowering::CopyToExportRegsIfNeeded(Value *V) { + if (!V->use_empty()) { + DenseMap::iterator VMI = FuncInfo.ValueMap.find(V); + if (VMI != FuncInfo.ValueMap.end()) + CopyValueToVirtualRegister(V, VMI->second); + } +} + /// ExportFromCurrentBlock - If this condition isn't known to be exported from /// the current basic block, add it to ValueMap now so that we'll get a /// CopyTo/FromReg. @@ -1572,11 +1583,7 @@ // If the value of the invoke is used outside of its defining block, make it // available as a virtual register. - if (!I.use_empty()) { - DenseMap::iterator VMI = FuncInfo.ValueMap.find(&I); - if (VMI != FuncInfo.ValueMap.end()) - CopyValueToVirtualRegister(&I, VMI->second); - } + CopyToExportRegsIfNeeded(&I); // Update successor info CurMBB->addSuccessor(Return); @@ -5924,10 +5931,7 @@ SDL->getCurDebugLoc())); // If this argument is live outside of the entry block, insert a copy from // whereever we got it to the vreg that other BB's will reference it as. - DenseMap::iterator VMI=FuncInfo->ValueMap.find(AI); - if (VMI != FuncInfo->ValueMap.end()) { - SDL->CopyValueToVirtualRegister(AI, VMI->second); - } + SDL->CopyToExportRegsIfNeeded(AI); } a += NumValues; } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h?rev=69937&r1=69936&r2=69937&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h Thu Apr 23 18:13:24 2009 @@ -422,6 +422,7 @@ MachineBasicBlock *CurBB); bool ShouldEmitAsBranches(const std::vector &Cases); bool isExportableFromCurrentBlock(Value *V, const BasicBlock *FromBB); + void CopyToExportRegsIfNeeded(Value *V); void ExportFromCurrentBlock(Value *V); void LowerCallTo(CallSite CS, SDValue Callee, bool IsTailCall, MachineBasicBlock *LandingPad = NULL); Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=69937&r1=69936&r2=69937&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Thu Apr 23 18:13:24 2009 @@ -476,11 +476,8 @@ // Ensure that all instructions which are used outside of their defining // blocks are available as virtual registers. Invoke is handled elsewhere. for (BasicBlock::iterator I = Begin; I != End; ++I) - if (!I->use_empty() && !isa(I) && !isa(I)) { - DenseMap::iterator VMI =FuncInfo->ValueMap.find(I); - if (VMI != FuncInfo->ValueMap.end()) - SDL->CopyValueToVirtualRegister(I, VMI->second); - } + if (!isa(I) && !isa(I)) + SDL->CopyToExportRegsIfNeeded(I); // Handle PHI nodes in successor blocks. if (End == LLVMBB->end()) { From dalej at apple.com Thu Apr 23 18:53:44 2009 From: dalej at apple.com (Dale Johannesen) Date: Thu, 23 Apr 2009 16:53:44 -0700 Subject: [llvm-commits] [llvm-gcc-4.2] r69795 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp In-Reply-To: <0D37D7F2-8DC9-42D6-B9B1-F64F9C003EEA@apple.com> References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu> <200904231003.37841.baldrick@free.fr> <17D0DDD6-5B1E-48FE-919D-11FB8FA93FC2@apple.com> <0D37D7F2-8DC9-42D6-B9B1-F64F9C003EEA@apple.com> Message-ID: <46672C4C-8B30-4C11-88A9-014EADD32FB7@apple.com> On Apr 23, 2009, at 10:12 AMPDT, Chris Lattner wrote: > > On Apr 23, 2009, at 10:04 AM, Dale Johannesen wrote: > >> >> On Apr 23, 2009, at 1:03 AMPDT, Duncan Sands wrote: >> >>> Hi Chris, >>> >>>> Thanks for doing this. Do you have a testcase? >>> >>> I only have an Ada testcase, and since you can't even build >>> the Ada front-end without this fix it seemed rather pointless >>> to add it to the testsuite. >> >> A C++ test affected by this bug is g++.old-deja/g++.jason/bool2.C . >> I'll put it in the llvm testsuite. > > Ah, nice, thanks Dale! Can you verify that the correct code is > generated on ppc for it? Yes, it is. From jyasskin at google.com Thu Apr 23 20:26:07 2009 From: jyasskin at google.com (Jeffrey Yasskin) Date: Thu, 23 Apr 2009 18:26:07 -0700 Subject: [llvm-commits] Add ConstantInt::getSigned() Message-ID: I got annoyed at the compiler warnings from ConstantInt::get(Ty, -1, true), and casts make me nervous and are verbose anyway, so here's a ConstantInt::getSigned(Ty, int64_t) method. Just overloading ConstantInt::get() to take an int64_t too would cause ambiguous overload errors. Jeffrey -------------- next part -------------- A non-text attachment was scrubbed... Name: getsigned.patch Type: application/octet-stream Size: 2310 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090423/b367bff1/attachment.obj From gohman at apple.com Thu Apr 23 21:10:40 2009 From: gohman at apple.com (Dan Gohman) Date: Thu, 23 Apr 2009 19:10:40 -0700 Subject: [llvm-commits] [llvm] r69574 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <49F0988B.5040000@microchip.com> References: <200904200605.n3K65sgm009422@zion.cs.uiuc.edu> <83B4B74F-3F9C-4A66-8447-40970738F0AD@apple.com> <49EC9FCB.7040501@microchip.com> <49F0988B.5040000@microchip.com> Message-ID: This looks good to me. It may not even be needed to limit indices to 16, 32, and 64; offhand it would seem that any integer type should work. But, that's only of theoretical interest until someone actually needs it. On Apr 23, 2009, at 9:34 AM, Sanjiv Gupta wrote: > > Index: lib/VMCore/Type.cpp > =================================================================== > --- lib/VMCore/Type.cpp (revision 69882) > +++ lib/VMCore/Type.cpp (working copy) > @@ -1411,7 +1411,8 @@ > > bool SequentialType::indexValid(const Value *V) const { > if (const IntegerType *IT = dyn_cast(V->getType())) > - return IT->getBitWidth() == 32 || IT->getBitWidth() == 64; > + return IT->getBitWidth() == 16 || IT->getBitWidth() == 32 > + || IT->getBitWidth() == 64; LLVM style has the || on the first line, not the second. Thanks, Dan From sanjiv.gupta at microchip.com Thu Apr 23 21:37:54 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Fri, 24 Apr 2009 02:37:54 -0000 Subject: [llvm-commits] [llvm] r69946 - in /llvm/trunk: docs/LangRef.html lib/Transforms/Scalar/InstructionCombining.cpp lib/VMCore/Type.cpp Message-ID: <200904240237.n3O2bsqj032157@zion.cs.uiuc.edu> Author: sgupta Date: Thu Apr 23 21:37:54 2009 New Revision: 69946 URL: http://llvm.org/viewvc/llvm-project?rev=69946&view=rev Log: Allow i16 type indices to gep. Modified: llvm/trunk/docs/LangRef.html llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp llvm/trunk/lib/VMCore/Type.cpp Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=69946&r1=69945&r2=69946&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Thu Apr 23 21:37:54 2009 @@ -3629,7 +3629,8 @@

The type of each index argument depends on the type it is indexing into. When indexing into a (packed) structure, only i32 integer constants are allowed. When indexing into an array, pointer or vector, -only integers of 32 or 64 bits are allowed (also non-constants). 32-bit values +only integers of 16, 32 or 64 bits are allowed (also non-constants).16-bit +values will be sign extended to 32-bits if required, and 32-bit values will be sign extended to 64-bits if required.

For example, let's consider a C code fragment and how it gets @@ -3717,6 +3718,8 @@ %vptr = getelementptr {i32, <2 x i8>}* %svptr, i64 0, i32 1, i32 1 ; yields i8*:eptr %eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1 + ; yields i16*:iptr + %iptr = getelementptr [10 x i16]* @arr, i16 0, i16 0

Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69946&r1=69945&r2=69946&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Thu Apr 23 21:37:54 2009 @@ -10695,12 +10695,7 @@ gep_type_iterator GTI = gep_type_begin(GEP); for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); i != e; ++i, ++GTI) { - // Before trying to eliminate/introduce cast/ext/trunc to make - // indices as pointer types, make sure that the pointer size - // makes a valid sequential index. - const SequentialType *ST = dyn_cast(*GTI); - Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); - if (ST && ST->indexValid(PtrTypeVal)) { + if (isa(*GTI)) { if (CastInst *CI = dyn_cast(*i)) { if (CI->getOpcode() == Instruction::ZExt || CI->getOpcode() == Instruction::SExt) { Modified: llvm/trunk/lib/VMCore/Type.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=69946&r1=69945&r2=69946&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Type.cpp (original) +++ llvm/trunk/lib/VMCore/Type.cpp Thu Apr 23 21:37:54 2009 @@ -1411,7 +1411,8 @@ bool SequentialType::indexValid(const Value *V) const { if (const IntegerType *IT = dyn_cast(V->getType())) - return IT->getBitWidth() == 32 || IT->getBitWidth() == 64; + return IT->getBitWidth() == 16 || IT->getBitWidth() == 32 || + IT->getBitWidth() == 64; return false; } From gohman at apple.com Thu Apr 23 21:40:23 2009 From: gohman at apple.com (Dan Gohman) Date: Fri, 24 Apr 2009 02:40:23 -0000 Subject: [llvm-commits] [llvm] r69948 - /llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp Message-ID: <200904240240.n3O2eNMY032245@zion.cs.uiuc.edu> Author: djg Date: Thu Apr 23 21:40:23 2009 New Revision: 69948 URL: http://llvm.org/viewvc/llvm-project?rev=69948&view=rev Log: Instead of requiring TLI.LowerCallTo to return an ISD::BUILD_PAIR, use ISD::EXTRACT_ELEMENT. SelectionDAG has a special fast-path for the cast of an EXTRACT_ELEMENT with a BUILD_PAIR operand, for the common case. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp?rev=69948&r1=69947&r2=69948&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp Thu Apr 23 21:40:23 2009 @@ -860,9 +860,12 @@ RTLIB::ADD_F32, RTLIB::ADD_F64, RTLIB::ADD_F80, RTLIB::ADD_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FCEIL(SDNode *N, @@ -871,9 +874,12 @@ RTLIB::CEIL_F32, RTLIB::CEIL_F64, RTLIB::CEIL_F80, RTLIB::CEIL_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FCOS(SDNode *N, @@ -882,9 +888,12 @@ RTLIB::COS_F32, RTLIB::COS_F64, RTLIB::COS_F80, RTLIB::COS_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDValue &Lo, @@ -897,9 +906,12 @@ RTLIB::DIV_PPCF128), N->getValueType(0), Ops, 2, false, N->getDebugLoc()); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FEXP(SDNode *N, @@ -908,9 +920,12 @@ RTLIB::EXP_F32, RTLIB::EXP_F64, RTLIB::EXP_F80, RTLIB::EXP_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FEXP2(SDNode *N, @@ -919,9 +934,12 @@ RTLIB::EXP2_F32, RTLIB::EXP2_F64, RTLIB::EXP2_F80, RTLIB::EXP2_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N, @@ -930,9 +948,12 @@ RTLIB::FLOOR_F32,RTLIB::FLOOR_F64, RTLIB::FLOOR_F80,RTLIB::FLOOR_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FLOG(SDNode *N, @@ -941,9 +962,12 @@ RTLIB::LOG_F32, RTLIB::LOG_F64, RTLIB::LOG_F80, RTLIB::LOG_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FLOG2(SDNode *N, @@ -952,9 +976,12 @@ RTLIB::LOG2_F32, RTLIB::LOG2_F64, RTLIB::LOG2_F80, RTLIB::LOG2_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FLOG10(SDNode *N, @@ -963,9 +990,12 @@ RTLIB::LOG10_F32,RTLIB::LOG10_F64, RTLIB::LOG10_F80,RTLIB::LOG10_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDValue &Lo, @@ -978,9 +1008,12 @@ RTLIB::MUL_PPCF128), N->getValueType(0), Ops, 2, false, N->getDebugLoc()); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FNEARBYINT(SDNode *N, @@ -991,9 +1024,12 @@ RTLIB::NEARBYINT_F80, RTLIB::NEARBYINT_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo, @@ -1017,9 +1053,12 @@ RTLIB::POW_F32, RTLIB::POW_F64, RTLIB::POW_F80, RTLIB::POW_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FPOWI(SDNode *N, @@ -1028,9 +1067,12 @@ RTLIB::POWI_F32, RTLIB::POWI_F64, RTLIB::POWI_F80, RTLIB::POWI_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FRINT(SDNode *N, @@ -1039,9 +1081,12 @@ RTLIB::RINT_F32, RTLIB::RINT_F64, RTLIB::RINT_F80, RTLIB::RINT_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FSIN(SDNode *N, @@ -1050,9 +1095,12 @@ RTLIB::SIN_F32, RTLIB::SIN_F64, RTLIB::SIN_F80, RTLIB::SIN_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FSQRT(SDNode *N, @@ -1061,9 +1109,12 @@ RTLIB::SQRT_F32, RTLIB::SQRT_F64, RTLIB::SQRT_F80, RTLIB::SQRT_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDValue &Lo, @@ -1076,9 +1127,12 @@ RTLIB::SUB_PPCF128), N->getValueType(0), Ops, 2, false, N->getDebugLoc()); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_FTRUNC(SDNode *N, @@ -1087,9 +1141,12 @@ RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, RTLIB::TRUNC_F80, RTLIB::TRUNC_PPCF128), N, false); - assert(Call.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Call.getOperand(0); Hi = Call.getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, + DAG.getIntPtrConstant(1)); } void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo, @@ -1157,9 +1214,10 @@ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!"); Hi = MakeLibCall(LC, VT, &Src, 1, true, dl); - assert(Hi.getNode()->getOpcode() == ISD::BUILD_PAIR && - "Call lowered wrongly!"); - Lo = Hi.getOperand(0); Hi = Hi.getOperand(1); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Hi, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Hi, + DAG.getIntPtrConstant(1)); } if (isSigned) From natebegeman at mac.com Thu Apr 23 22:42:57 2009 From: natebegeman at mac.com (Nate Begeman) Date: Fri, 24 Apr 2009 03:42:57 -0000 Subject: [llvm-commits] [llvm] r69952 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/CellSPU/ lib/Target/PowerPC/ lib/Target/X86/ test/CodeGen/X86/ utils/TableGen/ Message-ID: <200904240343.n3O3h13J001960@zion.cs.uiuc.edu> Author: sampo Date: Thu Apr 23 22:42:54 2009 New Revision: 69952 URL: http://llvm.org/viewvc/llvm-project?rev=69952&view=rev Log: PR2957 ISD::VECTOR_SHUFFLE now stores an array of integers representing the shuffle mask internal to the node, rather than taking a BUILD_VECTOR of ConstantSDNodes as the shuffle mask. A value of -1 represents UNDEF. In addition to eliminating the creation of illegal BUILD_VECTORS just to represent shuffle masks, we are better about canonicalizing the shuffle mask, resulting in substantially better code for some classes of shuffles. A clean up of x86 shuffle code, and some canonicalizing in DAGCombiner is next. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h llvm/trunk/include/llvm/Target/TargetLowering.h llvm/trunk/include/llvm/Target/TargetSelectionDAG.td llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86ISelLowering.h llvm/trunk/lib/Target/X86/X86InstrInfo.td llvm/trunk/lib/Target/X86/X86InstrMMX.td llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/test/CodeGen/X86/vec_clear.ll llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Thu Apr 23 22:42:54 2009 @@ -353,6 +353,13 @@ SDValue getConvertRndSat(MVT VT, DebugLoc dl, SDValue Val, SDValue DTy, SDValue STy, SDValue Rnd, SDValue Sat, ISD::CvtCode Code); + + /// getVectorShuffle - Return an ISD::VECTOR_SHUFFLE node. The number of + /// elements in VT, which must be a vector type, must match the number of + /// mask elements NumElts. A negative integer mask element is treated as + /// undefined. + SDValue getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, + const int *MaskElts); /// getZeroExtendInReg - Return the expression required to zero extend the Op /// value assuming it was the smaller SrcTy value. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Thu Apr 23 22:42:54 2009 @@ -1703,6 +1703,32 @@ } }; +class ShuffleVectorSDNode : public SDNode { + SDUse Ops[2]; + int *Mask; +protected: + friend class SelectionDAG; + ShuffleVectorSDNode(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, int *M) + : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) { + InitOperands(Ops, N1, N2); + } +public: + + const int * getMask() const { return Mask; } + + bool isSplat() { return isSplatMask(Mask, getValueType(0)); } + int getSplatIndex() { + assert(isSplat() && "Cannot get splat index for non-splat!"); + return Mask[0]; + } + static bool isSplatMask(const int *Mask, MVT VT); + + static bool classof(const ShuffleVectorSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::VECTOR_SHUFFLE; + } +}; + class ConstantSDNode : public SDNode { const ConstantInt *Value; friend class SelectionDAG; @@ -2084,7 +2110,7 @@ return N->getOpcode() == ISD::CONDCODE; } }; - + /// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the /// future and most targets don't support it. class CvtRndSatSDNode : public SDNode { Modified: llvm/trunk/include/llvm/Target/TargetLowering.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetLowering.h (original) +++ llvm/trunk/include/llvm/Target/TargetLowering.h Thu Apr 23 22:42:54 2009 @@ -328,7 +328,7 @@ /// support *some* VECTOR_SHUFFLE operations, those with specific masks. /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values /// are assumed to be legal. - virtual bool isShuffleMaskLegal(SDValue Mask, MVT VT) const { + virtual bool isShuffleMaskLegal(const int *Mask, MVT VT) const { return true; } @@ -336,9 +336,7 @@ /// used by Targets can use this to indicate if there is a suitable /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant /// pool entry. - virtual bool isVectorClearMaskLegal(const std::vector &BVOps, - MVT EVT, - SelectionDAG &DAG) const { + virtual bool isVectorClearMaskLegal(const int *Mask, MVT VT) const { return false; } Modified: llvm/trunk/include/llvm/Target/TargetSelectionDAG.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetSelectionDAG.td?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetSelectionDAG.td (original) +++ llvm/trunk/include/llvm/Target/TargetSelectionDAG.td Thu Apr 23 22:42:54 2009 @@ -51,15 +51,6 @@ int BigOperandNum = BigOp; } -/// SDTCisIntVectorOfSameSize - This indicates that ThisOp and OtherOp are -/// vector types, and that ThisOp is the result of -/// MVT::getIntVectorWithNumElements with the number of elements -/// that ThisOp has. -class SDTCisIntVectorOfSameSize - : SDTypeConstraint { - int OtherOpNum = OtherOp; -} - /// SDTCisEltOfVec - This indicates that ThisOp is a scalar type of the same /// type as the element type of OtherOp, which is a vector type. class SDTCisEltOfVec @@ -175,8 +166,8 @@ SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3> ]>; -def SDTVecShuffle : SDTypeProfile<1, 3, [ - SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisIntVectorOfSameSize<3, 0> +def SDTVecShuffle : SDTypeProfile<1, 2, [ + SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> ]>; def SDTVecExtract : SDTypeProfile<1, 2, [ // vector extract SDTCisEltOfVec<0, 1>, SDTCisPtrTy<2> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Thu Apr 23 22:42:54 2009 @@ -5098,7 +5098,21 @@ return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), InVec.getValueType(), &Ops[0], Ops.size()); } + // If the invec is an UNDEF and if EltNo is a constant, create a new + // BUILD_VECTOR with undef elements and the inserted element. + if (!LegalOperations && InVec.getOpcode() == ISD::UNDEF && + isa(EltNo)) { + MVT VT = InVec.getValueType(); + MVT EVT = VT.getVectorElementType(); + unsigned NElts = VT.getVectorNumElements(); + SmallVector Ops(NElts, DAG.getUNDEF(EVT)); + unsigned Elt = cast(EltNo)->getZExtValue(); + if (Elt < Ops.size()) + Ops[Elt] = InVal; + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + InVec.getValueType(), &Ops[0], Ops.size()); + } return SDValue(); } @@ -5160,9 +5174,8 @@ // to examine the mask. if (BCNumEltsChanged) return SDValue(); - unsigned Idx = cast(InVec.getOperand(2). - getOperand(Elt))->getZExtValue(); - unsigned NumElems = InVec.getOperand(2).getNumOperands(); + int Idx = cast(InVec)->getMask()[Elt]; + int NumElems = InVec.getValueType().getVectorNumElements(); InVec = (Idx < NumElems) ? InVec.getOperand(0) : InVec.getOperand(1); if (InVec.getOpcode() == ISD::BIT_CONVERT) InVec = InVec.getOperand(0); @@ -5209,7 +5222,6 @@ SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *N) { unsigned NumInScalars = N->getNumOperands(); MVT VT = N->getValueType(0); - unsigned NumElts = VT.getVectorNumElements(); MVT EltType = VT.getVectorElementType(); // Check to see if this is a BUILD_VECTOR of a bunch of EXTRACT_VECTOR_ELT @@ -5252,56 +5264,36 @@ } // If everything is good, we can make a shuffle operation. - MVT IndexVT = MVT::i32; if (VecIn1.getNode()) { - SmallVector BuildVecIndices; + SmallVector Mask; for (unsigned i = 0; i != NumInScalars; ++i) { if (N->getOperand(i).getOpcode() == ISD::UNDEF) { - BuildVecIndices.push_back(DAG.getUNDEF(IndexVT)); + Mask.push_back(-1); continue; } - SDValue Extract = N->getOperand(i); - // If extracting from the first vector, just use the index directly. + SDValue Extract = N->getOperand(i); SDValue ExtVal = Extract.getOperand(1); if (Extract.getOperand(0) == VecIn1) { - if (ExtVal.getValueType() == IndexVT) - BuildVecIndices.push_back(ExtVal); - else { - unsigned Idx = cast(ExtVal)->getZExtValue(); - BuildVecIndices.push_back(DAG.getConstant(Idx, IndexVT)); - } + Mask.push_back(cast(ExtVal)->getZExtValue()); continue; } // Otherwise, use InIdx + VecSize unsigned Idx = cast(ExtVal)->getZExtValue(); - BuildVecIndices.push_back(DAG.getConstant(Idx+NumInScalars, IndexVT)); + Mask.push_back(Idx+NumInScalars); } // Add count and size info. - MVT BuildVecVT = MVT::getVectorVT(IndexVT, NumElts); - if (!TLI.isTypeLegal(BuildVecVT) && LegalTypes) + if (!TLI.isTypeLegal(VT) && LegalTypes) return SDValue(); // Return the new VECTOR_SHUFFLE node. - SDValue Ops[5]; + SDValue Ops[2]; Ops[0] = VecIn1; - if (VecIn2.getNode()) { - Ops[1] = VecIn2; - } else { - // Use an undef build_vector as input for the second operand. - std::vector UnOps(NumInScalars, - DAG.getUNDEF(EltType)); - Ops[1] = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT, - &UnOps[0], UnOps.size()); - AddToWorkList(Ops[1].getNode()); - } - - Ops[2] = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), BuildVecVT, - &BuildVecIndices[0], BuildVecIndices.size()); - return DAG.getNode(ISD::VECTOR_SHUFFLE, N->getDebugLoc(), VT, Ops, 3); + Ops[1] = VecIn2.getNode() ? VecIn2 : DAG.getUNDEF(VT); + return DAG.getVectorShuffle(VT, N->getDebugLoc(), Ops[0], Ops[1], &Mask[0]); } return SDValue(); @@ -5321,8 +5313,10 @@ } SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { - SDValue ShufMask = N->getOperand(2); - unsigned NumElts = ShufMask.getNumOperands(); + return SDValue(); + + MVT VT = N->getValueType(0); + unsigned NumElts = VT.getVectorNumElements(); SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -5330,60 +5324,13 @@ assert(N0.getValueType().getVectorNumElements() == NumElts && "Vector shuffle must be normalized in DAG"); - // If the shuffle mask is an identity operation on the LHS, return the LHS. - bool isIdentity = true; - for (unsigned i = 0; i != NumElts; ++i) { - if (ShufMask.getOperand(i).getOpcode() != ISD::UNDEF && - cast(ShufMask.getOperand(i))->getZExtValue() != i) { - isIdentity = false; - break; - } - } - if (isIdentity) return N->getOperand(0); - - // If the shuffle mask is an identity operation on the RHS, return the RHS. - isIdentity = true; - for (unsigned i = 0; i != NumElts; ++i) { - if (ShufMask.getOperand(i).getOpcode() != ISD::UNDEF && - cast(ShufMask.getOperand(i))->getZExtValue() != - i+NumElts) { - isIdentity = false; - break; - } - } - if (isIdentity) return N->getOperand(1); - - // Check if the shuffle is a unary shuffle, i.e. one of the vectors is not - // needed at all. - bool isUnary = true; - bool isSplat = true; - int VecNum = -1; - unsigned BaseIdx = 0; - for (unsigned i = 0; i != NumElts; ++i) - if (ShufMask.getOperand(i).getOpcode() != ISD::UNDEF) { - unsigned Idx=cast(ShufMask.getOperand(i))->getZExtValue(); - int V = (Idx < NumElts) ? 0 : 1; - if (VecNum == -1) { - VecNum = V; - BaseIdx = Idx; - } else { - if (BaseIdx != Idx) - isSplat = false; - if (VecNum != V) { - isUnary = false; - break; - } - } - } - - // Normalize unary shuffle so the RHS is undef. - if (isUnary && VecNum == 1) - std::swap(N0, N1); + // FIXME: implement canonicalizations from DAG.getVectorShuffle() // If it is a splat, check if the argument vector is a build_vector with // all scalar elements the same. - if (isSplat) { + if (cast(N)->isSplat()) { SDNode *V = N0.getNode(); + // If this is a bit convert that changes the element type of the vector but // not the number of vector elements, look through it. Be careful not to @@ -5397,6 +5344,7 @@ if (V->getOpcode() == ISD::BUILD_VECTOR) { unsigned NumElems = V->getNumOperands(); + unsigned BaseIdx = cast(N)->getSplatIndex(); if (NumElems > BaseIdx) { SDValue Base; bool AllSame = true; @@ -5421,38 +5369,6 @@ } } } - - // If it is a unary or the LHS and the RHS are the same node, turn the RHS - // into an undef. - if (isUnary || N0 == N1) { - // Check the SHUFFLE mask, mapping any inputs from the 2nd operand into the - // first operand. - SmallVector MappedOps; - - for (unsigned i = 0; i != NumElts; ++i) { - if (ShufMask.getOperand(i).getOpcode() == ISD::UNDEF || - cast(ShufMask.getOperand(i))->getZExtValue() < - NumElts) { - MappedOps.push_back(ShufMask.getOperand(i)); - } else { - unsigned NewIdx = - cast(ShufMask.getOperand(i))->getZExtValue() - - NumElts; - MappedOps.push_back(DAG.getConstant(NewIdx, - ShufMask.getOperand(i).getValueType())); - } - } - - ShufMask = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), - ShufMask.getValueType(), - &MappedOps[0], MappedOps.size()); - AddToWorkList(ShufMask.getNode()); - return DAG.getNode(ISD::VECTOR_SHUFFLE, N->getDebugLoc(), - N->getValueType(0), N0, - DAG.getUNDEF(N->getValueType(0)), - ShufMask); - } - return SDValue(); } @@ -5461,52 +5377,42 @@ /// e.g. AND V, <0xffffffff, 0, 0xffffffff, 0>. ==> /// vector_shuffle V, Zero, <0, 4, 2, 4> SDValue DAGCombiner::XformToShuffleWithZero(SDNode *N) { + MVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); SDValue LHS = N->getOperand(0); SDValue RHS = N->getOperand(1); if (N->getOpcode() == ISD::AND) { if (RHS.getOpcode() == ISD::BIT_CONVERT) RHS = RHS.getOperand(0); if (RHS.getOpcode() == ISD::BUILD_VECTOR) { - std::vector IdxOps; - unsigned NumOps = RHS.getNumOperands(); - unsigned NumElts = NumOps; + SmallVector Indices; + unsigned NumElts = RHS.getNumOperands(); for (unsigned i = 0; i != NumElts; ++i) { SDValue Elt = RHS.getOperand(i); if (!isa(Elt)) return SDValue(); else if (cast(Elt)->isAllOnesValue()) - IdxOps.push_back(DAG.getIntPtrConstant(i)); + Indices.push_back(i); else if (cast(Elt)->isNullValue()) - IdxOps.push_back(DAG.getIntPtrConstant(NumElts)); + Indices.push_back(NumElts); else return SDValue(); } // Let's see if the target supports this vector_shuffle. - if (!TLI.isVectorClearMaskLegal(IdxOps, TLI.getPointerTy(), DAG)) + MVT RVT = RHS.getValueType(); + if (!TLI.isVectorClearMaskLegal(&Indices[0], RVT)) return SDValue(); // Return the new VECTOR_SHUFFLE node. - MVT EVT = RHS.getValueType().getVectorElementType(); - MVT VT = MVT::getVectorVT(EVT, NumElts); - MVT MaskVT = MVT::getVectorVT(TLI.getPointerTy(), NumElts); - std::vector Ops; - LHS = DAG.getNode(ISD::BIT_CONVERT, LHS.getDebugLoc(), VT, LHS); - Ops.push_back(LHS); - AddToWorkList(LHS.getNode()); - std::vector ZeroOps(NumElts, DAG.getConstant(0, EVT)); - Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), - VT, &ZeroOps[0], ZeroOps.size())); - Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), - MaskVT, &IdxOps[0], IdxOps.size())); - SDValue Result = DAG.getNode(ISD::VECTOR_SHUFFLE, N->getDebugLoc(), - VT, &Ops[0], Ops.size()); - - if (VT != N->getValueType(0)) - Result = DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), - N->getValueType(0), Result); - - return Result; + MVT EVT = RVT.getVectorElementType(); + SmallVector ZeroOps(RVT.getVectorNumElements(), + DAG.getConstant(0, EVT)); + SDValue Zero = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + RVT, &ZeroOps[0], ZeroOps.size()); + LHS = DAG.getNode(ISD::BIT_CONVERT, dl, RVT, LHS); + SDValue Shuf = DAG.getVectorShuffle(RVT, dl, LHS, Zero, &Indices[0]); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Shuf); } } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Thu Apr 23 22:42:54 2009 @@ -267,16 +267,10 @@ bool isVolatile, SDValue ValOp, unsigned StWidth, DebugLoc dl); - /// isShuffleLegal - Return non-null if a vector shuffle is legal with the - /// specified mask and type. Targets can specify exactly which masks they - /// support and the code generator is tasked with not creating illegal masks. - /// - /// Note that this will also return true for shuffles that are promoted to a - /// different type. - /// - /// If this is a legal shuffle, this method returns the (possibly promoted) - /// build_vector Mask. If it's not a legal shuffle, it returns null. - SDNode *isShuffleLegal(MVT VT, SDValue Mask) const; + /// promoteShuffle - Promote a shuffle mask of a vector VT to perform the + /// same shuffle on a vector of NVT. Must not create an illegal shuffle mask. + SDValue promoteShuffle(MVT NVT, MVT VT, DebugLoc dl, SDValue N1, SDValue N2, + const int *Mask) const; bool LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest, SmallPtrSet &NodesLeadingTo); @@ -319,50 +313,35 @@ }; } -/// isVectorShuffleLegal - Return true if a vector shuffle is legal with the -/// specified mask and type. Targets can specify exactly which masks they -/// support and the code generator is tasked with not creating illegal masks. -/// -/// Note that this will also return true for shuffles that are promoted to a -/// different type. -SDNode *SelectionDAGLegalize::isShuffleLegal(MVT VT, SDValue Mask) const { - switch (TLI.getOperationAction(ISD::VECTOR_SHUFFLE, VT)) { - default: return 0; - case TargetLowering::Legal: - case TargetLowering::Custom: - break; - case TargetLowering::Promote: { - // If this is promoted to a different type, convert the shuffle mask and - // ask if it is legal in the promoted type! - MVT NVT = TLI.getTypeToPromoteTo(ISD::VECTOR_SHUFFLE, VT); - MVT EltVT = NVT.getVectorElementType(); - - // If we changed # elements, change the shuffle mask. - unsigned NumEltsGrowth = - NVT.getVectorNumElements() / VT.getVectorNumElements(); - assert(NumEltsGrowth && "Cannot promote to vector type with fewer elts!"); - if (NumEltsGrowth > 1) { - // Renumber the elements. - SmallVector Ops; - for (unsigned i = 0, e = Mask.getNumOperands(); i != e; ++i) { - SDValue InOp = Mask.getOperand(i); - for (unsigned j = 0; j != NumEltsGrowth; ++j) { - if (InOp.getOpcode() == ISD::UNDEF) - Ops.push_back(DAG.getUNDEF(EltVT)); - else { - unsigned InEltNo = cast(InOp)->getZExtValue(); - Ops.push_back(DAG.getConstant(InEltNo*NumEltsGrowth+j, EltVT)); - } - } - } - Mask = DAG.getNode(ISD::BUILD_VECTOR, Mask.getDebugLoc(), - NVT, &Ops[0], Ops.size()); +/// promoteShuffle - Promote a shuffle mask of a vector VT to perform the +/// same shuffle on a vector of NVT. Must not create an illegal shuffle mask. +/// e.g. <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3> +SDValue SelectionDAGLegalize::promoteShuffle(MVT NVT, MVT VT, DebugLoc dl, + SDValue N1, SDValue N2, + const int *Mask) const { + MVT EltVT = NVT.getVectorElementType(); + int NumMaskElts = VT.getVectorNumElements(); + int NumDestElts = NVT.getVectorNumElements(); + unsigned NumEltsGrowth = NumDestElts / NumMaskElts; + + assert(NumEltsGrowth && "Cannot promote to vector type with fewer elts!"); + + if (NumEltsGrowth == 1) + return DAG.getVectorShuffle(NVT, dl, N1, N2, Mask); + + SmallVector NewMask; + for (int i = 0; i != NumMaskElts; ++i) { + int Idx = Mask[i]; + for (unsigned j = 0; j != NumEltsGrowth; ++j) { + if (Idx < 0) + NewMask.push_back(-1); + else + NewMask.push_back(Idx * NumEltsGrowth + j); } - VT = NVT; - break; - } } - return TLI.isShuffleMaskLegal(Mask, VT) ? Mask.getNode() : 0; + assert((int)NewMask.size() == NumDestElts && "Non-integer NumEltsGrowth?"); + assert(TLI.isShuffleMaskLegal(&Mask[0], NVT) && "Shuffle not legal?"); + return DAG.getVectorShuffle(NVT, dl, N1, N2, &NewMask[0]); } SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag, @@ -1652,25 +1631,15 @@ Tmp1.getValueType(), Tmp2); unsigned NumElts = Tmp1.getValueType().getVectorNumElements(); - MVT ShufMaskVT = - MVT::getIntVectorWithNumElements(NumElts); - MVT ShufMaskEltVT = ShufMaskVT.getVectorElementType(); - // We generate a shuffle of InVec and ScVec, so the shuffle mask // should be 0,1,2,3,4,5... with the appropriate element replaced with // elt 0 of the RHS. - SmallVector ShufOps; - for (unsigned i = 0; i != NumElts; ++i) { - if (i != InsertPos->getZExtValue()) - ShufOps.push_back(DAG.getConstant(i, ShufMaskEltVT)); - else - ShufOps.push_back(DAG.getConstant(NumElts, ShufMaskEltVT)); - } - SDValue ShufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, ShufMaskVT, - &ShufOps[0], ShufOps.size()); - - Result = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, Tmp1.getValueType(), - Tmp1, ScVec, ShufMask); + SmallVector ShufOps; + for (unsigned i = 0; i != NumElts; ++i) + ShufOps.push_back(i != InsertPos->getZExtValue() ? i : NumElts); + + Result = DAG.getVectorShuffle(Tmp1.getValueType(), dl, Tmp1, ScVec, + &ShufOps[0]); Result = LegalizeOp(Result); break; } @@ -1708,13 +1677,14 @@ case ISD::VECTOR_SHUFFLE: Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the input vectors, Tmp2 = LegalizeOp(Node->getOperand(1)); // but not the shuffle mask. - Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2)); + Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); // Allow targets to custom lower the SHUFFLEs they support. switch (TLI.getOperationAction(ISD::VECTOR_SHUFFLE, Result.getValueType())){ default: assert(0 && "Unknown operation action!"); case TargetLowering::Legal: - assert(isShuffleLegal(Result.getValueType(), Node->getOperand(2)) && + assert(TLI.isShuffleMaskLegal(cast(Node)->getMask(), + Result.getValueType()) && "vector shuffle should not be created if not legal!"); break; case TargetLowering::Custom: @@ -1728,23 +1698,21 @@ MVT VT = Node->getValueType(0); MVT EltVT = VT.getVectorElementType(); MVT PtrVT = TLI.getPointerTy(); - SDValue Mask = Node->getOperand(2); - unsigned NumElems = Mask.getNumOperands(); + const int *Mask = cast(Node)->getMask(); + int NumElems = VT.getVectorNumElements(); SmallVector Ops; - for (unsigned i = 0; i != NumElems; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) { + for (int i = 0; i != NumElems; ++i) { + if (Mask[i] < 0) { Ops.push_back(DAG.getUNDEF(EltVT)); - } else { - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - unsigned Idx = cast(Arg)->getZExtValue(); - if (Idx < NumElems) - Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Tmp1, - DAG.getConstant(Idx, PtrVT))); - else - Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Tmp2, - DAG.getConstant(Idx - NumElems, PtrVT))); + continue; } + int Idx = Mask[i]; + if (Idx < NumElems) + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Tmp1, + DAG.getConstant(Idx, PtrVT))); + else + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Tmp2, + DAG.getConstant(Idx - NumElems, PtrVT))); } Result = DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], Ops.size()); break; @@ -1759,9 +1727,8 @@ Tmp2 = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Tmp2); // Convert the shuffle mask to the right # elements. - Tmp3 = SDValue(isShuffleLegal(OVT, Node->getOperand(2)), 0); - assert(Tmp3.getNode() && "Shuffle not legal?"); - Result = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, NVT, Tmp1, Tmp2, Tmp3); + Result = promoteShuffle(NVT, OVT, dl, Tmp1, Tmp2, + cast(Node)->getMask()); Result = DAG.getNode(ISD::BIT_CONVERT, dl, OVT, Result); break; } @@ -5490,6 +5457,7 @@ // FIXME: it would be far nicer to change this into map // and use a bitmask instead of a list of elements. + // FIXME: this doesn't treat <0, u, 0, u> for example, as a splat. std::map > Values; Values[SplatValue].push_back(0); bool isConstant = true; @@ -5546,21 +5514,17 @@ if (SplatValue.getNode()) { // Splat of one value? // Build the shuffle constant vector: <0, 0, 0, 0> - MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); - SDValue Zero = DAG.getConstant(0, MaskVT.getVectorElementType()); - std::vector ZeroVec(NumElems, Zero); - SDValue SplatMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &ZeroVec[0], ZeroVec.size()); + SmallVector ZeroVec(NumElems, 0); // If the target supports VECTOR_SHUFFLE and this shuffle mask, use it. - if (isShuffleLegal(VT, SplatMask)) { + if (TLI.isShuffleMaskLegal(&ZeroVec[0], Node->getValueType(0))) { // Get the splatted value into the low element of a vector register. SDValue LowValVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, SplatValue); // Return shuffle(LowValVec, undef, <0,0,0,0>) - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, LowValVec, - DAG.getUNDEF(VT), SplatMask); + return DAG.getVectorShuffle(VT, dl, LowValVec, DAG.getUNDEF(VT), + &ZeroVec[0]); } } @@ -5582,35 +5546,25 @@ std::swap(Val1, Val2); // Build the shuffle constant vector: e.g. <0, 4, 0, 4> - MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); - MVT MaskEltVT = MaskVT.getVectorElementType(); - std::vector MaskVec(NumElems); + SmallVector ShuffleMask(NumElems, -1); // Set elements of the shuffle mask for Val1. std::vector &Val1Elts = Values[Val1]; for (unsigned i = 0, e = Val1Elts.size(); i != e; ++i) - MaskVec[Val1Elts[i]] = DAG.getConstant(0, MaskEltVT); + ShuffleMask[Val1Elts[i]] = 0; // Set elements of the shuffle mask for Val2. std::vector &Val2Elts = Values[Val2]; for (unsigned i = 0, e = Val2Elts.size(); i != e; ++i) if (Val2.getOpcode() != ISD::UNDEF) - MaskVec[Val2Elts[i]] = DAG.getConstant(NumElems, MaskEltVT); - else - MaskVec[Val2Elts[i]] = DAG.getUNDEF(MaskEltVT); - - SDValue ShuffleMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskVec[0], MaskVec.size()); + ShuffleMask[Val2Elts[i]] = NumElems; // If the target supports SCALAR_TO_VECTOR and this shuffle mask, use it. if (TLI.isOperationLegalOrCustom(ISD::SCALAR_TO_VECTOR, VT) && - isShuffleLegal(VT, ShuffleMask)) { + TLI.isShuffleMaskLegal(&ShuffleMask[0], VT)) { Val1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Val1); Val2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Val2); - SDValue Ops[] = { Val1, Val2, ShuffleMask }; - - // Return shuffle(LoValVec, HiValVec, <0,1,0,1>) - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, Ops, 3); + return DAG.getVectorShuffle(VT, dl, Val1, Val2, &ShuffleMask[0]); } } @@ -8066,36 +8020,19 @@ case ISD::VECTOR_SHUFFLE: { SDValue Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT); SDValue Tmp2 = WidenVectorOp(Node->getOperand(1), WidenVT); - // VECTOR_SHUFFLE 3rd operand must be a constant build vector that is - // used as permutation array. We build the vector here instead of widening - // because we don't want to legalize and have it turned to something else. - SDValue PermOp = Node->getOperand(2); - SDValueVector NewOps; - MVT PVT = PermOp.getValueType().getVectorElementType(); + const int *Mask = cast(Node)->getMask(); + SmallVector NewMask; for (unsigned i = 0; i < NumElts; ++i) { - if (PermOp.getOperand(i).getOpcode() == ISD::UNDEF) { - NewOps.push_back(PermOp.getOperand(i)); - } else { - unsigned Idx = - cast(PermOp.getOperand(i))->getZExtValue(); - if (Idx < NumElts) { - NewOps.push_back(PermOp.getOperand(i)); - } - else { - NewOps.push_back(DAG.getConstant(Idx + NewNumElts - NumElts, - PermOp.getOperand(i).getValueType())); - } - } - } - for (unsigned i = NumElts; i < NewNumElts; ++i) { - NewOps.push_back(DAG.getUNDEF(PVT)); + int Idx = Mask[i]; + if (Idx < (int)NumElts) + NewMask.push_back(Idx); + else + NewMask.push_back(Idx + NewNumElts - NumElts); } - - SDValue Tmp3 = DAG.getNode(ISD::BUILD_VECTOR, dl, - MVT::getVectorVT(PVT, NewOps.size()), - &NewOps[0], NewOps.size()); - - Result = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, WidenVT, Tmp1, Tmp2, Tmp3); + for (unsigned i = NumElts; i < NewNumElts; ++i) + NewMask.push_back(-1); + + Result = DAG.getVectorShuffle(WidenVT, dl, Tmp1, Tmp2, &NewMask[0]); break; } case ISD::LOAD: { Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Thu Apr 23 22:42:54 2009 @@ -772,10 +772,8 @@ // If Lo or Hi uses elements from at most two of the four input vectors, then // express it as a vector shuffle of those two inputs. Otherwise extract the // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR. - SDValue Mask = N->getOperand(2); - MVT IdxVT = Mask.getValueType().getVectorElementType(); - SmallVector Ops; - Ops.reserve(NewElts); + const int *Mask = cast(N)->getMask(); + SmallVector Ops; for (unsigned High = 0; High < 2; ++High) { SDValue &Output = High ? Hi : Lo; @@ -787,18 +785,15 @@ unsigned FirstMaskIdx = High * NewElts; bool useBuildVector = false; for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { - SDValue Arg = Mask.getOperand(FirstMaskIdx + MaskOffset); - // The mask element. This indexes into the input. - unsigned Idx = Arg.getOpcode() == ISD::UNDEF ? - -1U : cast(Arg)->getZExtValue(); + int Idx = Mask[FirstMaskIdx + MaskOffset]; // The input vector this mask element indexes into. - unsigned Input = Idx / NewElts; + unsigned Input = (unsigned)Idx / NewElts; if (Input >= array_lengthof(Inputs)) { // The mask element does not index into any input vector. - Ops.push_back(DAG.getUNDEF(IdxVT)); + Ops.push_back(-1); continue; } @@ -826,27 +821,24 @@ } // Add the mask index for the new shuffle vector. - Ops.push_back(DAG.getConstant(Idx + OpNo * NewElts, IdxVT)); + Ops.push_back(Idx + OpNo * NewElts); } if (useBuildVector) { MVT EltVT = NewVT.getVectorElementType(); - Ops.clear(); + SmallVector SVOps; // Extract the input elements by hand. for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { - SDValue Arg = Mask.getOperand(FirstMaskIdx + MaskOffset); - // The mask element. This indexes into the input. - unsigned Idx = Arg.getOpcode() == ISD::UNDEF ? - -1U : cast(Arg)->getZExtValue(); + int Idx = Mask[FirstMaskIdx + MaskOffset]; // The input vector this mask element indexes into. - unsigned Input = Idx / NewElts; + unsigned Input = (unsigned)Idx / NewElts; if (Input >= array_lengthof(Inputs)) { // The mask element is "undef" or indexes off the end of the input. - Ops.push_back(DAG.getUNDEF(EltVT)); + SVOps.push_back(DAG.getUNDEF(EltVT)); continue; } @@ -854,25 +846,22 @@ Idx -= Input * NewElts; // Extract the vector element by hand. - Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, - Inputs[Input], DAG.getIntPtrConstant(Idx))); + SVOps.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, + Inputs[Input], DAG.getIntPtrConstant(Idx))); } // Construct the Lo/Hi output using a BUILD_VECTOR. - Output = DAG.getNode(ISD::BUILD_VECTOR, dl, NewVT, &Ops[0], Ops.size()); + Output = DAG.getNode(ISD::BUILD_VECTOR,dl,NewVT, &SVOps[0], SVOps.size()); } else if (InputUsed[0] == -1U) { // No input vectors were used! The result is undefined. Output = DAG.getUNDEF(NewVT); } else { - // At least one input vector was used. Create a new shuffle vector. - SDValue NewMask = DAG.getNode(ISD::BUILD_VECTOR, dl, - MVT::getVectorVT(IdxVT, Ops.size()), - &Ops[0], Ops.size()); SDValue Op0 = Inputs[InputUsed[0]]; // If only one input was used, use an undefined vector for the other. SDValue Op1 = InputUsed[1] == -1U ? DAG.getUNDEF(NewVT) : Inputs[InputUsed[1]]; - Output = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, NewVT, Op0, Op1, NewMask); + // At least one input vector was used. Create a new shuffle vector. + Output = DAG.getVectorShuffle(NewVT, dl, Op0, Op1, &Ops[0]); } Ops.clear(); @@ -1473,18 +1462,15 @@ if (NumOperands == 2) { // Replace concat of two operands with a shuffle. - MVT PtrVT = TLI.getPointerTy(); - SmallVector MaskOps(WidenNumElts); + SmallVector MaskOps(WidenNumElts); for (unsigned i=0; i < WidenNumElts/2; ++i) { - MaskOps[i] = DAG.getConstant(i, PtrVT); - MaskOps[i+WidenNumElts/2] = DAG.getConstant(i+WidenNumElts, PtrVT); + MaskOps[i] = i; + MaskOps[i+WidenNumElts/2] = i+WidenNumElts; } - SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, - MVT::getVectorVT(PtrVT, WidenNumElts), - &MaskOps[0], WidenNumElts); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, WidenVT, - GetWidenedVector(N->getOperand(0)), - GetWidenedVector(N->getOperand(1)), Mask); + return DAG.getVectorShuffle(WidenVT, dl, + GetWidenedVector(N->getOperand(0)), + GetWidenedVector(N->getOperand(1)), + &MaskOps[0]); } } } @@ -1762,7 +1748,7 @@ SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(SDNode *N) { MVT VT = N->getValueType(0); - unsigned NumElts = VT.getVectorNumElements(); + int NumElts = VT.getVectorNumElements(); DebugLoc dl = N->getDebugLoc(); MVT WidenVT = TLI.getTypeToTransformTo(VT); @@ -1772,28 +1758,17 @@ SDValue InOp2 = GetWidenedVector(N->getOperand(1)); // Adjust mask based on new input vector length. - SDValue Mask = N->getOperand(2); - SmallVector MaskOps(WidenNumElts); - MVT IdxVT = Mask.getValueType().getVectorElementType(); - for (unsigned i = 0; i < NumElts; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) - MaskOps[i] = Arg; - else { - unsigned Idx = cast(Arg)->getZExtValue(); - if (Idx < NumElts) - MaskOps[i] = Arg; - else - MaskOps[i] = DAG.getConstant(Idx - NumElts + WidenNumElts, IdxVT); - } + const int *Mask = cast(N)->getMask(); + SmallVector NewMask; + for (int i = 0; i < NumElts; ++i) { + if (Mask[i] < NumElts) + NewMask.push_back(Mask[i]); + else + NewMask.push_back(Mask[i] - NumElts + WidenNumElts); } for (unsigned i = NumElts; i < WidenNumElts; ++i) - MaskOps[i] = DAG.getUNDEF(IdxVT); - SDValue NewMask = DAG.getNode(ISD::BUILD_VECTOR, dl, - MVT::getVectorVT(IdxVT, WidenNumElts), - &MaskOps[0], WidenNumElts); - - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, WidenVT, InOp1, InOp2, NewMask); + NewMask.push_back(-1); + return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, &NewMask[0]); } SDValue DAGTypeLegalizer::WidenVecRes_VSETCC(SDNode *N) { Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Thu Apr 23 22:42:54 2009 @@ -456,6 +456,13 @@ ID.AddInteger(AT->getRawSubclassData()); break; } + case ISD::VECTOR_SHUFFLE: { + const int *Mask = cast(N)->getMask(); + for (unsigned i = 0, e = N->getValueType(0).getVectorNumElements(); + i != e; ++i) + ID.AddInteger(Mask[i]); + break; + } } // end switch (N->getOpcode()) } @@ -762,12 +769,6 @@ assert(N->getValueType(0).isVector() && "Wrong return type!"); assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() && "Wrong number of operands!"); - MVT EltVT = N->getValueType(0).getVectorElementType(); - for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) - assert((I->getValueType() == EltVT || - (EltVT.isInteger() && I->getValueType().isInteger() && - EltVT.bitsLE(I->getValueType()))) && - "Wrong operand type!"); break; } } @@ -1126,6 +1127,110 @@ return SDValue(CondCodeNodes[Cond], 0); } +static void commuteShuffle(SDValue &N1, SDValue &N2, SmallVectorImpl &M) { + std::swap(N1, N2); + int NElts = M.size(); + for (int i = 0; i != NElts; ++i) { + if (M[i] >= NElts) + M[i] -= NElts; + else if (M[i] >= 0) + M[i] += NElts; + } +} + +SDValue SelectionDAG::getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, + SDValue N2, const int *Mask) { + assert(N1.getValueType() == N2.getValueType() && "Invalid VECTOR_SHUFFLE"); + assert(VT.isVector() && N1.getValueType().isVector() && + "Vector Shuffle VTs must be a vectors"); + assert(VT.getVectorElementType() == N1.getValueType().getVectorElementType() + && "Vector Shuffle VTs must have same element type"); + + // Canonicalize shuffle undef, undef -> undef + if (N1.getOpcode() == ISD::UNDEF && N2.getOpcode() == ISD::UNDEF) + return N1; + + // Validate that all the indices past in in Mask are within the range of + // elements input to the shuffle. + int NElts = VT.getVectorNumElements(); + SmallVector MaskVec; + for (int i = 0; i != NElts; ++i) { + if (Mask[i] >= (NElts * 2)) { + assert(0 && "Index out of range"); + return SDValue(); + } + MaskVec.push_back(Mask[i]); + } + + // Canonicalize shuffle v, v -> v, undef + if (N1 == N2) { + N2 = getUNDEF(VT); + for (int i = 0; i != NElts; ++i) + if (MaskVec[i] >= NElts) MaskVec[i] -= NElts; + } + + // Canonicalize shuffle undef, v -> v, undef. Commute the shuffle mask. + if (N1.getOpcode() == ISD::UNDEF) + commuteShuffle(N1, N2, MaskVec); + + // Canonicalize all index into lhs, -> shuffle lhs, undef + // Canonicalize all index into rhs, -> shuffle rhs, undef + bool AllLHS = true, AllRHS = true; + bool N2Undef = N2.getOpcode() == ISD::UNDEF; + for (int i = 0; i != NElts; ++i) { + if (MaskVec[i] >= NElts) { + if (N2Undef) + MaskVec[i] = -1; + else + AllLHS = false; + } else if (MaskVec[i] >= 0) { + AllRHS = false; + } + } + if (AllLHS && AllRHS) + return getUNDEF(VT); + if (AllLHS) + N2 = getUNDEF(VT); + if (AllRHS) { + N1 = getUNDEF(VT); + commuteShuffle(N1, N2, MaskVec); + } + + // If Identity shuffle, or all shuffle in to undef, return that node. + bool AllUndef = true; + bool Identity = true; + for (int i = 0; i < NElts; ++i) { + if (MaskVec[i] >= 0 && MaskVec[i] != i) Identity = false; + if (MaskVec[i] >= 0) AllUndef = false; + } + if (Identity) + return N1; + if (AllUndef) + return getUNDEF(VT); + + FoldingSetNodeID ID; + SDValue Ops[2] = { N1, N2 }; + AddNodeIDNode(ID, ISD::VECTOR_SHUFFLE, getVTList(VT), Ops, 2); + for (int i = 0; i != NElts; ++i) + ID.AddInteger(MaskVec[i]); + + void* IP = 0; + 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 + // the node is deallocated, but recovered when the NodeAllocator is released. + int *MaskAlloc = OperandAllocator.Allocate(NElts); + memcpy(MaskAlloc, &MaskVec[0], NElts * sizeof(int)); + + ShuffleVectorSDNode *N = NodeAllocator.Allocate(); + new (N) ShuffleVectorSDNode(VT, dl, N1, N2, MaskAlloc); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getConvertRndSat(MVT VT, DebugLoc dl, SDValue Val, SDValue DTy, SDValue STy, SDValue Rnd, SDValue Sat, @@ -2087,19 +2192,18 @@ SDValue SelectionDAG::getShuffleScalarElt(const SDNode *N, unsigned i) { MVT VT = N->getValueType(0); DebugLoc dl = N->getDebugLoc(); - SDValue PermMask = N->getOperand(2); - SDValue Idx = PermMask.getOperand(i); - if (Idx.getOpcode() == ISD::UNDEF) + const int *PermMask = cast(N)->getMask(); + if (PermMask[i] < 0) return getUNDEF(VT.getVectorElementType()); - unsigned Index = cast(Idx)->getZExtValue(); - unsigned NumElems = PermMask.getNumOperands(); + int Index = PermMask[i]; + int NumElems = VT.getVectorNumElements(); SDValue V = (Index < NumElems) ? N->getOperand(0) : N->getOperand(1); Index %= NumElems; if (V.getOpcode() == ISD::BIT_CONVERT) { V = V.getOperand(0); MVT VVT = V.getValueType(); - if (!VVT.isVector() || VVT.getVectorNumElements() != NumElems) + if (!VVT.isVector() || VVT.getVectorNumElements() != (unsigned)NumElems) return SDValue(); } if (V.getOpcode() == ISD::SCALAR_TO_VECTOR) @@ -2793,12 +2897,7 @@ } break; case ISD::VECTOR_SHUFFLE: - assert(N1.getValueType() == N2.getValueType() && - N1.getValueType().isVector() && - VT.isVector() && N3.getValueType().isVector() && - N3.getOpcode() == ISD::BUILD_VECTOR && - VT.getVectorNumElements() == N3.getNumOperands() && - "Illegal VECTOR_SHUFFLE node!"); + assert(0 && "should use getVectorShuffle constructor!"); break; case ISD::BIT_CONVERT: // Fold bit_convert nodes from a type to themselves. @@ -5322,14 +5421,14 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { if (!isTargetOpcode() && getOpcode() == ISD::VECTOR_SHUFFLE) { - SDNode *Mask = getOperand(2).getNode(); + const int *Mask = cast(this)->getMask(); OS << "<"; - for (unsigned i = 0, e = Mask->getNumOperands(); i != e; ++i) { + for (unsigned i = 0, e = ValueList[0].getVectorNumElements(); i != e; ++i) { if (i) OS << ","; - if (Mask->getOperand(i).getOpcode() == ISD::UNDEF) + if (Mask[i] < 0) OS << "u"; else - OS << cast(Mask->getOperand(i))->getZExtValue(); + OS << Mask[i]; } OS << ">"; } @@ -5610,3 +5709,13 @@ SplatBitSize = sz; return true; } + +bool ShuffleVectorSDNode::isSplatMask(const int *Mask, MVT VT) { + int Idx = -1; + for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { + if (Idx < 0) Idx = Mask[i]; + if (Mask[i] >= 0 && Mask[i] != Idx) + return false; + } + return true; +} Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Thu Apr 23 22:42:54 2009 @@ -870,8 +870,7 @@ if (ConstantFP *CFP = dyn_cast(C)) return N = DAG.getConstantFP(*CFP, VT); - if (isa(C) && !isa(V->getType()) && - !V->getType()->isAggregateType()) + if (isa(C) && !V->getType()->isAggregateType()) return N = DAG.getUNDEF(VT); if (ConstantExpr *CE = dyn_cast(C)) { @@ -925,14 +924,11 @@ for (unsigned i = 0; i != NumElements; ++i) Ops.push_back(getValue(CP->getOperand(i))); } else { - assert((isa(C) || isa(C)) && - "Unknown vector constant!"); + assert(isa(C) && "Unknown vector constant!"); MVT EltVT = TLI.getValueType(VecTy->getElementType()); SDValue Op; - if (isa(C)) - Op = DAG.getUNDEF(EltVT); - else if (EltVT.isFloatingPoint()) + if (EltVT.isFloatingPoint()) Op = DAG.getConstantFP(0, EltVT); else Op = DAG.getConstant(0, EltVT); @@ -2435,37 +2431,42 @@ // Utility for visitShuffleVector - Returns true if the mask is mask starting // from SIndx and increasing to the element length (undefs are allowed). -static bool SequentialMask(SDValue Mask, unsigned SIndx) { - unsigned MaskNumElts = Mask.getNumOperands(); - for (unsigned i = 0; i != MaskNumElts; ++i) { - if (Mask.getOperand(i).getOpcode() != ISD::UNDEF) { - unsigned Idx = cast(Mask.getOperand(i))->getZExtValue(); - if (Idx != i + SIndx) - return false; - } - } +static bool SequentialMask(SmallVectorImpl &Mask, int SIndx) { + int MaskNumElts = Mask.size(); + for (int i = 0; i != MaskNumElts; ++i) + if ((Mask[i] >= 0) && (Mask[i] != i + SIndx)) + return false; return true; } void SelectionDAGLowering::visitShuffleVector(User &I) { + SmallVector Mask; SDValue Src1 = getValue(I.getOperand(0)); SDValue Src2 = getValue(I.getOperand(1)); - SDValue Mask = getValue(I.getOperand(2)); + // Convert the ConstantVector mask operand into an array of ints, with -1 + // representing undef values. + SmallVector MaskElts; + cast(I.getOperand(2))->getVectorElements(MaskElts); + int MaskNumElts = MaskElts.size(); + for (int i = 0; i != MaskNumElts; ++i) { + if (isa(MaskElts[i])) + Mask.push_back(-1); + else + Mask.push_back(cast(MaskElts[i])->getSExtValue()); + } + MVT VT = TLI.getValueType(I.getType()); MVT SrcVT = Src1.getValueType(); - int MaskNumElts = Mask.getNumOperands(); int SrcNumElts = SrcVT.getVectorNumElements(); if (SrcNumElts == MaskNumElts) { - setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, getCurDebugLoc(), - VT, Src1, Src2, Mask)); + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &Mask[0])); return; } // Normalize the shuffle vector since mask and vector length don't match. - MVT MaskEltVT = Mask.getValueType().getVectorElementType(); - if (SrcNumElts < MaskNumElts && MaskNumElts % SrcNumElts == 0) { // Mask is longer than the source vectors and is a multiple of the source // vectors. We can use concatenate vector to make the mask and vectors @@ -2479,44 +2480,33 @@ // Pad both vectors with undefs to make them the same length as the mask. unsigned NumConcat = MaskNumElts / SrcNumElts; + bool Src1U = Src1.getOpcode() == ISD::UNDEF; + bool Src2U = Src2.getOpcode() == ISD::UNDEF; SDValue UndefVal = DAG.getUNDEF(SrcVT); - SDValue* MOps1 = new SDValue[NumConcat]; - SDValue* MOps2 = new SDValue[NumConcat]; + SmallVector MOps1(NumConcat, UndefVal); + SmallVector MOps2(NumConcat, UndefVal); MOps1[0] = Src1; MOps2[0] = Src2; - for (unsigned i = 1; i != NumConcat; ++i) { - MOps1[i] = UndefVal; - MOps2[i] = UndefVal; - } - Src1 = DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(), - VT, MOps1, NumConcat); - Src2 = DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(), - VT, MOps2, NumConcat); - - delete [] MOps1; - delete [] MOps2; + + Src1 = Src1U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS, + getCurDebugLoc(), VT, + &MOps1[0], NumConcat); + Src2 = Src2U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS, + getCurDebugLoc(), VT, + &MOps2[0], NumConcat); // Readjust mask for new input vector length. - SmallVector MappedOps; + SmallVector MappedOps; for (int i = 0; i != MaskNumElts; ++i) { - if (Mask.getOperand(i).getOpcode() == ISD::UNDEF) { - MappedOps.push_back(Mask.getOperand(i)); - } else { - int Idx = cast(Mask.getOperand(i))->getZExtValue(); - if (Idx < SrcNumElts) - MappedOps.push_back(DAG.getConstant(Idx, MaskEltVT)); - else - MappedOps.push_back(DAG.getConstant(Idx + MaskNumElts - SrcNumElts, - MaskEltVT)); - } + int Idx = Mask[i]; + if (Idx < SrcNumElts) + MappedOps.push_back(Idx); + else + MappedOps.push_back(Idx + MaskNumElts - SrcNumElts); } - Mask = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), - Mask.getValueType(), - &MappedOps[0], MappedOps.size()); - - setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, getCurDebugLoc(), - VT, Src1, Src2, Mask)); + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &MappedOps[0])); return; } @@ -2541,20 +2531,19 @@ int MaxRange[2] = {-1, -1}; for (int i = 0; i != MaskNumElts; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() != ISD::UNDEF) { - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - int Idx = cast(Arg)->getZExtValue(); - int Input = 0; - if (Idx >= SrcNumElts) { - Input = 1; - Idx -= SrcNumElts; - } - if (Idx > MaxRange[Input]) - MaxRange[Input] = Idx; - if (Idx < MinRange[Input]) - MinRange[Input] = Idx; - } + int Idx = Mask[i]; + int Input = 0; + if (Idx < 0) + continue; + + if (Idx >= SrcNumElts) { + Input = 1; + Idx -= SrcNumElts; + } + if (Idx > MaxRange[Input]) + MaxRange[Input] = Idx; + if (Idx < MinRange[Input]) + MinRange[Input] = Idx; } // Check if the access is smaller than the vector size and can we find @@ -2596,26 +2585,18 @@ } } // Calculate new mask. - SmallVector MappedOps; + SmallVector MappedOps; for (int i = 0; i != MaskNumElts; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) { - MappedOps.push_back(Arg); - } else { - int Idx = cast(Arg)->getZExtValue(); - if (Idx < SrcNumElts) - MappedOps.push_back(DAG.getConstant(Idx - StartIdx[0], MaskEltVT)); - else { - Idx = Idx - SrcNumElts - StartIdx[1] + MaskNumElts; - MappedOps.push_back(DAG.getConstant(Idx, MaskEltVT)); - } - } + int Idx = Mask[i]; + if (Idx < 0) + MappedOps.push_back(Idx); + else if (Idx < SrcNumElts) + MappedOps.push_back(Idx - StartIdx[0]); + else + MappedOps.push_back(Idx - SrcNumElts - StartIdx[1] + MaskNumElts); } - Mask = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), - Mask.getValueType(), - &MappedOps[0], MappedOps.size()); - setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, getCurDebugLoc(), - VT, Src1, Src2, Mask)); + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &MappedOps[0])); return; } } @@ -2627,12 +2608,10 @@ MVT PtrVT = TLI.getPointerTy(); SmallVector Ops; for (int i = 0; i != MaskNumElts; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) { + if (Mask[i] < 0) { Ops.push_back(DAG.getUNDEF(EltVT)); } else { - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - int Idx = cast(Arg)->getZExtValue(); + int Idx = Mask[i]; if (Idx < SrcNumElts) Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), EltVT, Src1, DAG.getConstant(Idx, PtrVT))); Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp (original) +++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp Thu Apr 23 22:42:54 2009 @@ -1672,7 +1672,7 @@ static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { SDValue V1 = Op.getOperand(0); SDValue V2 = Op.getOperand(1); - SDValue PermMask = Op.getOperand(2); + const int *PermMask = cast(Op)->getMask(); DebugLoc dl = Op.getDebugLoc(); if (V2.getOpcode() == ISD::UNDEF) V2 = V1; @@ -1703,39 +1703,40 @@ } else assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE"); - for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) { - if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) { - unsigned SrcElt = cast (PermMask.getOperand(i))->getZExtValue(); - - if (monotonic) { - if (SrcElt >= V2EltIdx0) { - if (1 >= (++EltsFromV2)) { - V2Elt = (V2EltIdx0 - SrcElt) << 2; - } - } else if (CurrElt != SrcElt) { - monotonic = false; + for (unsigned i = 0; i != MaxElts; ++i) { + if (PermMask[i] < 0) + continue; + + unsigned SrcElt = PermMask[i]; + + if (monotonic) { + if (SrcElt >= V2EltIdx0) { + if (1 >= (++EltsFromV2)) { + V2Elt = (V2EltIdx0 - SrcElt) << 2; } - - ++CurrElt; + } else if (CurrElt != SrcElt) { + monotonic = false; } - if (rotate) { - if (PrevElt > 0 && SrcElt < MaxElts) { - if ((PrevElt == SrcElt - 1) - || (PrevElt == MaxElts - 1 && SrcElt == 0)) { - PrevElt = SrcElt; - if (SrcElt == 0) - V0Elt = i; - } else { - rotate = false; - } - } else if (PrevElt == 0) { - // First time through, need to keep track of previous element + ++CurrElt; + } + + if (rotate) { + if (PrevElt > 0 && SrcElt < MaxElts) { + if ((PrevElt == SrcElt - 1) + || (PrevElt == MaxElts - 1 && SrcElt == 0)) { PrevElt = SrcElt; + if (SrcElt == 0) + V0Elt = i; } else { - // This isn't a rotation, takes elements from vector 2 rotate = false; } + } else if (PrevElt == 0) { + // First time through, need to keep track of previous element + PrevElt = SrcElt; + } else { + // This isn't a rotation, takes elements from vector 2 + rotate = false; } } } @@ -1768,12 +1769,8 @@ unsigned BytesPerElement = EltVT.getSizeInBits()/8; SmallVector ResultMask; - for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) { - unsigned SrcElt; - if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF) - SrcElt = 0; - else - SrcElt = cast(PermMask.getOperand(i))->getZExtValue(); + for (unsigned i = 0, e = MaxElts; i != e; ++i) { + unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i]; for (unsigned j = 0; j < BytesPerElement; ++j) { ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j, Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Thu Apr 23 22:42:54 2009 @@ -456,22 +456,22 @@ /// isConstantOrUndef - Op is either an undef node or a ConstantSDNode. Return /// true if Op is undef or if it matches the specified value. -static bool isConstantOrUndef(SDValue Op, unsigned Val) { - return Op.getOpcode() == ISD::UNDEF || - cast(Op)->getZExtValue() == Val; +static bool isConstantOrUndef(int Op, int Val) { + return Op < 0 || Op == Val; } /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUHUM instruction. -bool PPC::isVPKUHUMShuffleMask(SDNode *N, bool isUnary) { +bool PPC::isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { + const int *Mask = N->getMask(); if (!isUnary) { for (unsigned i = 0; i != 16; ++i) - if (!isConstantOrUndef(N->getOperand(i), i*2+1)) + if (!isConstantOrUndef(Mask[i], i*2+1)) return false; } else { for (unsigned i = 0; i != 8; ++i) - if (!isConstantOrUndef(N->getOperand(i), i*2+1) || - !isConstantOrUndef(N->getOperand(i+8), i*2+1)) + if (!isConstantOrUndef(Mask[i], i*2+1) || + !isConstantOrUndef(Mask[i+8], i*2+1)) return false; } return true; @@ -479,18 +479,19 @@ /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUWUM instruction. -bool PPC::isVPKUWUMShuffleMask(SDNode *N, bool isUnary) { +bool PPC::isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { + const int *Mask = N->getMask(); if (!isUnary) { for (unsigned i = 0; i != 16; i += 2) - if (!isConstantOrUndef(N->getOperand(i ), i*2+2) || - !isConstantOrUndef(N->getOperand(i+1), i*2+3)) + if (!isConstantOrUndef(Mask[i ], i*2+2) || + !isConstantOrUndef(Mask[i+1], i*2+3)) return false; } else { for (unsigned i = 0; i != 8; i += 2) - if (!isConstantOrUndef(N->getOperand(i ), i*2+2) || - !isConstantOrUndef(N->getOperand(i+1), i*2+3) || - !isConstantOrUndef(N->getOperand(i+8), i*2+2) || - !isConstantOrUndef(N->getOperand(i+9), i*2+3)) + if (!isConstantOrUndef(Mask[i ], i*2+2) || + !isConstantOrUndef(Mask[i+1], i*2+3) || + !isConstantOrUndef(Mask[i+8], i*2+2) || + !isConstantOrUndef(Mask[i+9], i*2+3)) return false; } return true; @@ -498,27 +499,29 @@ /// isVMerge - Common function, used to match vmrg* shuffles. /// -static bool isVMerge(SDNode *N, unsigned UnitSize, +static bool isVMerge(ShuffleVectorSDNode *N, unsigned UnitSize, unsigned LHSStart, unsigned RHSStart) { - assert(N->getOpcode() == ISD::BUILD_VECTOR && - N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); + assert(N->getValueType(0) == MVT::v16i8 && + "PPC only supports shuffles by bytes!"); assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && "Unsupported merge size!"); + const int *Mask = N->getMask(); for (unsigned i = 0; i != 8/UnitSize; ++i) // Step over units for (unsigned j = 0; j != UnitSize; ++j) { // Step over bytes within unit - if (!isConstantOrUndef(N->getOperand(i*UnitSize*2+j), + if (!isConstantOrUndef(Mask[i*UnitSize*2+j], LHSStart+j+i*UnitSize) || - !isConstantOrUndef(N->getOperand(i*UnitSize*2+UnitSize+j), + !isConstantOrUndef(Mask[i*UnitSize*2+UnitSize+j], RHSStart+j+i*UnitSize)) return false; } - return true; + return true; } /// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for /// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). -bool PPC::isVMRGLShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary) { +bool PPC::isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, + bool isUnary) { if (!isUnary) return isVMerge(N, UnitSize, 8, 24); return isVMerge(N, UnitSize, 8, 8); @@ -526,7 +529,8 @@ /// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). -bool PPC::isVMRGHShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary) { +bool PPC::isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, + bool isUnary) { if (!isUnary) return isVMerge(N, UnitSize, 0, 16); return isVMerge(N, UnitSize, 0, 0); @@ -536,91 +540,92 @@ /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// amount, otherwise return -1. int PPC::isVSLDOIShuffleMask(SDNode *N, bool isUnary) { - assert(N->getOpcode() == ISD::BUILD_VECTOR && - N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); + assert(N->getValueType(0) == MVT::v16i8 && + "PPC only supports shuffles by bytes!"); + + ShuffleVectorSDNode *SVOp = cast(N); + // Find the first non-undef value in the shuffle mask. + const int *Mask = SVOp->getMask(); unsigned i; - for (i = 0; i != 16 && N->getOperand(i).getOpcode() == ISD::UNDEF; ++i) + for (i = 0; i != 16 && Mask[i] < 0; ++i) /*search*/; if (i == 16) return -1; // all undef. - // Otherwise, check to see if the rest of the elements are consequtively + // Otherwise, check to see if the rest of the elements are consecutively // numbered from this value. - unsigned ShiftAmt = cast(N->getOperand(i))->getZExtValue(); + unsigned ShiftAmt = Mask[i]; if (ShiftAmt < i) return -1; ShiftAmt -= i; if (!isUnary) { - // Check the rest of the elements to see if they are consequtive. + // Check the rest of the elements to see if they are consecutive. for (++i; i != 16; ++i) - if (!isConstantOrUndef(N->getOperand(i), ShiftAmt+i)) + if (!isConstantOrUndef(Mask[i], ShiftAmt+i)) return -1; } else { - // Check the rest of the elements to see if they are consequtive. + // Check the rest of the elements to see if they are consecutive. for (++i; i != 16; ++i) - if (!isConstantOrUndef(N->getOperand(i), (ShiftAmt+i) & 15)) + if (!isConstantOrUndef(Mask[i], (ShiftAmt+i) & 15)) return -1; } - return ShiftAmt; } /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a splat of a single element that is suitable for input to /// VSPLTB/VSPLTH/VSPLTW. -bool PPC::isSplatShuffleMask(SDNode *N, unsigned EltSize) { - assert(N->getOpcode() == ISD::BUILD_VECTOR && - N->getNumOperands() == 16 && +bool PPC::isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize) { + assert(N->getValueType(0) == MVT::v16i8 && (EltSize == 1 || EltSize == 2 || EltSize == 4)); // This is a splat operation if each element of the permute is the same, and // if the value doesn't reference the second vector. - unsigned ElementBase = 0; - SDValue Elt = N->getOperand(0); - if (ConstantSDNode *EltV = dyn_cast(Elt)) - ElementBase = EltV->getZExtValue(); - else - return false; // FIXME: Handle UNDEF elements too! - - if (cast(Elt)->getZExtValue() >= 16) + const int *Mask = N->getMask(); + unsigned ElementBase = Mask[0]; + + // FIXME: Handle UNDEF elements too! + if (ElementBase >= 16) return false; - // Check that they are consequtive. - for (unsigned i = 1; i != EltSize; ++i) { - if (!isa(N->getOperand(i)) || - cast(N->getOperand(i))->getZExtValue() != i+ElementBase) + // Check that the indices are consecutive, in the case of a multi-byte element + // splatted with a v16i8 mask. + for (unsigned i = 1; i != EltSize; ++i) + if (Mask[i] < 0 || Mask[i] != (int)(i+ElementBase)) return false; - } - assert(isa(Elt) && "Invalid VECTOR_SHUFFLE mask!"); for (unsigned i = EltSize, e = 16; i != e; i += EltSize) { - if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; - assert(isa(N->getOperand(i)) && - "Invalid VECTOR_SHUFFLE mask!"); + if (Mask[i] < 0) continue; for (unsigned j = 0; j != EltSize; ++j) - if (N->getOperand(i+j) != N->getOperand(j)) + if (Mask[i+j] != Mask[j]) return false; } - return true; } /// isAllNegativeZeroVector - Returns true if all elements of build_vector /// are -0.0. bool PPC::isAllNegativeZeroVector(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - if (PPC::isSplatShuffleMask(N, N->getNumOperands())) - if (ConstantFPSDNode *CFP = dyn_cast(N)) + BuildVectorSDNode *BV = cast(N); + + APInt APVal, APUndef; + unsigned BitSize; + bool HasAnyUndefs; + + if (BV->isConstantSplat(APVal, APUndef, BitSize, HasAnyUndefs, 32)) + if (ConstantFPSDNode *CFP = dyn_cast(N->getOperand(0))) return CFP->getValueAPF().isNegZero(); + return false; } /// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the /// specified isSplatShuffleMask VECTOR_SHUFFLE mask. unsigned PPC::getVSPLTImmediate(SDNode *N, unsigned EltSize) { - assert(isSplatShuffleMask(N, EltSize)); - return cast(N->getOperand(0))->getZExtValue() / EltSize; + ShuffleVectorSDNode *SVOp = cast(N); + assert(isSplatShuffleMask(SVOp, EltSize)); + return SVOp->getMask()[0] / EltSize; } /// get_VSPLTI_elt - If this is a build_vector of constants which can be formed @@ -3149,11 +3154,10 @@ LHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, LHS); RHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, RHS); - SDValue Ops[16]; + int Ops[16]; for (unsigned i = 0; i != 16; ++i) - Ops[i] = DAG.getConstant(i+Amt, MVT::i8); - SDValue T = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v16i8, LHS, RHS, - DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8, Ops,16)); + Ops[i] = i + Amt; + SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, LHS, RHS, Ops); return DAG.getNode(ISD::BIT_CONVERT, dl, VT, T); } @@ -3354,7 +3358,7 @@ OpLHS = GeneratePerfectShuffle(PerfectShuffleTable[LHSID], LHS, RHS, DAG, dl); OpRHS = GeneratePerfectShuffle(PerfectShuffleTable[RHSID], LHS, RHS, DAG, dl); - unsigned ShufIdxs[16]; + int ShufIdxs[16]; switch (OpNum) { default: assert(0 && "Unknown i32 permute!"); case OP_VMRGHW: @@ -3392,13 +3396,11 @@ case OP_VSLDOI12: return BuildVSLDOI(OpLHS, OpRHS, 12, OpLHS.getValueType(), DAG, dl); } - SDValue Ops[16]; - for (unsigned i = 0; i != 16; ++i) - Ops[i] = DAG.getConstant(ShufIdxs[i], MVT::i8); - - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, OpLHS.getValueType(), - OpLHS, OpRHS, - DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8, Ops, 16)); + MVT VT = OpLHS.getValueType(); + OpLHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OpLHS); + OpRHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OpRHS); + SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, OpLHS, OpRHS, ShufIdxs); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, T); } /// LowerVECTOR_SHUFFLE - Return the code we lower for VECTOR_SHUFFLE. If this @@ -3406,28 +3408,30 @@ /// return the code it can be lowered into. Worst case, it can always be /// lowered into a vperm. SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, - SelectionDAG &DAG) { + SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); SDValue V1 = Op.getOperand(0); SDValue V2 = Op.getOperand(1); - SDValue PermMask = Op.getOperand(2); + ShuffleVectorSDNode *SVOp = cast(Op); + const int *PermMask = SVOp->getMask(); + MVT VT = Op.getValueType(); // Cases that are handled by instructions that take permute immediates // (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be // selected by the instruction selector. if (V2.getOpcode() == ISD::UNDEF) { - if (PPC::isSplatShuffleMask(PermMask.getNode(), 1) || - PPC::isSplatShuffleMask(PermMask.getNode(), 2) || - PPC::isSplatShuffleMask(PermMask.getNode(), 4) || - PPC::isVPKUWUMShuffleMask(PermMask.getNode(), true) || - PPC::isVPKUHUMShuffleMask(PermMask.getNode(), true) || - PPC::isVSLDOIShuffleMask(PermMask.getNode(), true) != -1 || - PPC::isVMRGLShuffleMask(PermMask.getNode(), 1, true) || - PPC::isVMRGLShuffleMask(PermMask.getNode(), 2, true) || - PPC::isVMRGLShuffleMask(PermMask.getNode(), 4, true) || - PPC::isVMRGHShuffleMask(PermMask.getNode(), 1, true) || - PPC::isVMRGHShuffleMask(PermMask.getNode(), 2, true) || - PPC::isVMRGHShuffleMask(PermMask.getNode(), 4, true)) { + if (PPC::isSplatShuffleMask(SVOp, 1) || + PPC::isSplatShuffleMask(SVOp, 2) || + PPC::isSplatShuffleMask(SVOp, 4) || + PPC::isVPKUWUMShuffleMask(SVOp, true) || + PPC::isVPKUHUMShuffleMask(SVOp, true) || + PPC::isVSLDOIShuffleMask(SVOp, true) != -1 || + PPC::isVMRGLShuffleMask(SVOp, 1, true) || + PPC::isVMRGLShuffleMask(SVOp, 2, true) || + PPC::isVMRGLShuffleMask(SVOp, 4, true) || + PPC::isVMRGHShuffleMask(SVOp, 1, true) || + PPC::isVMRGHShuffleMask(SVOp, 2, true) || + PPC::isVMRGHShuffleMask(SVOp, 4, true)) { return Op; } } @@ -3435,15 +3439,15 @@ // Altivec has a variety of "shuffle immediates" that take two vector inputs // and produce a fixed permutation. If any of these match, do not lower to // VPERM. - if (PPC::isVPKUWUMShuffleMask(PermMask.getNode(), false) || - PPC::isVPKUHUMShuffleMask(PermMask.getNode(), false) || - PPC::isVSLDOIShuffleMask(PermMask.getNode(), false) != -1 || - PPC::isVMRGLShuffleMask(PermMask.getNode(), 1, false) || - PPC::isVMRGLShuffleMask(PermMask.getNode(), 2, false) || - PPC::isVMRGLShuffleMask(PermMask.getNode(), 4, false) || - PPC::isVMRGHShuffleMask(PermMask.getNode(), 1, false) || - PPC::isVMRGHShuffleMask(PermMask.getNode(), 2, false) || - PPC::isVMRGHShuffleMask(PermMask.getNode(), 4, false)) + if (PPC::isVPKUWUMShuffleMask(SVOp, false) || + PPC::isVPKUHUMShuffleMask(SVOp, false) || + PPC::isVSLDOIShuffleMask(SVOp, false) != -1 || + PPC::isVMRGLShuffleMask(SVOp, 1, false) || + PPC::isVMRGLShuffleMask(SVOp, 2, false) || + PPC::isVMRGLShuffleMask(SVOp, 4, false) || + PPC::isVMRGHShuffleMask(SVOp, 1, false) || + PPC::isVMRGHShuffleMask(SVOp, 2, false) || + PPC::isVMRGHShuffleMask(SVOp, 4, false)) return Op; // Check to see if this is a shuffle of 4-byte values. If so, we can use our @@ -3453,11 +3457,10 @@ for (unsigned i = 0; i != 4 && isFourElementShuffle; ++i) { // Element number unsigned EltNo = 8; // Start out undef. for (unsigned j = 0; j != 4; ++j) { // Intra-element byte. - if (PermMask.getOperand(i*4+j).getOpcode() == ISD::UNDEF) + if (PermMask[i*4+j] < 0) continue; // Undef, ignore it. - unsigned ByteSource = - cast(PermMask.getOperand(i*4+j))->getZExtValue(); + unsigned ByteSource = PermMask[i*4+j]; if ((ByteSource & 3) != j) { isFourElementShuffle = false; break; @@ -3509,12 +3512,8 @@ unsigned BytesPerElement = EltVT.getSizeInBits()/8; SmallVector ResultMask; - for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) { - unsigned SrcElt; - if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF) - SrcElt = 0; - else - SrcElt = cast(PermMask.getOperand(i))->getZExtValue(); + for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { + unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i]; for (unsigned j = 0; j != BytesPerElement; ++j) ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j, @@ -3704,13 +3703,12 @@ OddParts = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OddParts); // Merge the results together. - SDValue Ops[16]; + int Ops[16]; for (unsigned i = 0; i != 8; ++i) { - Ops[i*2 ] = DAG.getConstant(2*i+1, MVT::i8); - Ops[i*2+1] = DAG.getConstant(2*i+1+16, MVT::i8); + Ops[i*2 ] = 2*i+1; + Ops[i*2+1] = 2*i+1+16; } - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v16i8, EvenParts, OddParts, - DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8, Ops, 16)); + return DAG.getVectorShuffle(MVT::v16i8, dl, EvenParts, OddParts, Ops); } else { assert(0 && "Unknown mul to lower!"); abort(); Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h (original) +++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h Thu Apr 23 22:42:54 2009 @@ -175,19 +175,21 @@ namespace PPC { /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUHUM instruction. - bool isVPKUHUMShuffleMask(SDNode *N, bool isUnary); + bool isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary); /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUWUM instruction. - bool isVPKUWUMShuffleMask(SDNode *N, bool isUnary); + bool isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary); /// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for /// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). - bool isVMRGLShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary); + bool isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, + bool isUnary); /// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). - bool isVMRGHShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary); + bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, + bool isUnary); /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// amount, otherwise return -1. @@ -196,7 +198,7 @@ /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a splat of a single element that is suitable for input to /// VSPLTB/VSPLTH/VSPLTW. - bool isSplatShuffleMask(SDNode *N, unsigned EltSize); + bool isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize); /// isAllNegativeZeroVector - Returns true if all elements of build_vector /// are -0.0. Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td (original) +++ llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td Thu Apr 23 22:42:54 2009 @@ -15,96 +15,118 @@ // Altivec transformation functions and pattern fragments. // -/// VPKUHUM_shuffle_mask/VPKUWUM_shuffle_mask - Return true if this is a valid -/// shuffle mask for the VPKUHUM or VPKUWUM instructions. -def VPKUHUM_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVPKUHUMShuffleMask(N, false); + +def vpkuhum_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVPKUHUMShuffleMask(cast(N), false); }]>; -def VPKUWUM_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVPKUWUMShuffleMask(N, false); +def vpkuwum_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVPKUWUMShuffleMask(cast(N), false); }]>; - -def VPKUHUM_unary_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVPKUHUMShuffleMask(N, true); +def vpkuhum_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVPKUHUMShuffleMask(cast(N), true); }]>; -def VPKUWUM_unary_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVPKUWUMShuffleMask(N, true); +def vpkuwum_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVPKUWUMShuffleMask(cast(N), true); }]>; -def VMRGLB_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGLShuffleMask(N, 1, false); +def vmrglb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 1, false); }]>; -def VMRGLH_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGLShuffleMask(N, 2, false); +def vmrglh_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 2, false); }]>; -def VMRGLW_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGLShuffleMask(N, 4, false); +def vmrglw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 4, false); }]>; -def VMRGHB_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGHShuffleMask(N, 1, false); +def vmrghb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 1, false); }]>; -def VMRGHH_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGHShuffleMask(N, 2, false); +def vmrghh_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 2, false); }]>; -def VMRGHW_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGHShuffleMask(N, 4, false); +def vmrghw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 4, false); }]>; -def VMRGLB_unary_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGLShuffleMask(N, 1, true); + +def vmrglb_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 1, true); }]>; -def VMRGLH_unary_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGLShuffleMask(N, 2, true); +def vmrglh_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 2, true); }]>; -def VMRGLW_unary_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGLShuffleMask(N, 4, true); +def vmrglw_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 4, true); }]>; -def VMRGHB_unary_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGHShuffleMask(N, 1, true); +def vmrghb_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 1, true); }]>; -def VMRGHH_unary_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGHShuffleMask(N, 2, true); +def vmrghh_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 2, true); }]>; -def VMRGHW_unary_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isVMRGHShuffleMask(N, 4, true); +def vmrghw_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 4, true); }]>; -def VSLDOI_get_imm : SDNodeXForm; -def VSLDOI_shuffle_mask : PatLeaf<(build_vector), [{ +def vsldoi_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ return PPC::isVSLDOIShuffleMask(N, false) != -1; }], VSLDOI_get_imm>; + /// VSLDOI_unary* - These are used to match vsldoi(X,X), which is turned into /// vector_shuffle(X,undef,mask) by the dag combiner. -def VSLDOI_unary_get_imm : SDNodeXForm; -def VSLDOI_unary_shuffle_mask : PatLeaf<(build_vector), [{ +def vsldoi_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ return PPC::isVSLDOIShuffleMask(N, true) != -1; }], VSLDOI_unary_get_imm>; // VSPLT*_get_imm xform function: convert vector_shuffle mask to VSPLT* imm. -def VSPLTB_get_imm : SDNodeXForm; -def VSPLTB_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isSplatShuffleMask(N, 1); +def vspltb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isSplatShuffleMask(cast(N), 1); }], VSPLTB_get_imm>; -def VSPLTH_get_imm : SDNodeXForm; -def VSPLTH_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isSplatShuffleMask(N, 2); +def vsplth_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isSplatShuffleMask(cast(N), 2); }], VSPLTH_get_imm>; -def VSPLTW_get_imm : SDNodeXForm; -def VSPLTW_shuffle_mask : PatLeaf<(build_vector), [{ - return PPC::isSplatShuffleMask(N, 4); +def vspltw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isSplatShuffleMask(cast(N), 4); }], VSPLTW_get_imm>; @@ -268,8 +290,7 @@ def VSLDOI : VAForm_2<44, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB, u5imm:$SH), "vsldoi $vD, $vA, $vB, $SH", VecFP, [(set VRRC:$vD, - (vector_shuffle (v16i8 VRRC:$vA), VRRC:$vB, - VSLDOI_shuffle_mask:$SH))]>; + (vsldoi_shuffle:$SH (v16i8 VRRC:$vA), VRRC:$vB))]>; // VX-Form instructions. AltiVec arithmetic ops. def VADDFP : VXForm_1<10, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), @@ -345,28 +366,22 @@ def VMRGHB : VXForm_1< 12, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrghb $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), - VRRC:$vB, VMRGHB_shuffle_mask))]>; + [(set VRRC:$vD, (vmrghb_shuffle VRRC:$vA, VRRC:$vB))]>; def VMRGHH : VXForm_1< 76, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrghh $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), - VRRC:$vB, VMRGHH_shuffle_mask))]>; + [(set VRRC:$vD, (vmrghh_shuffle VRRC:$vA, VRRC:$vB))]>; def VMRGHW : VXForm_1<140, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrghw $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), - VRRC:$vB, VMRGHW_shuffle_mask))]>; + [(set VRRC:$vD, (vmrghw_shuffle VRRC:$vA, VRRC:$vB))]>; def VMRGLB : VXForm_1<268, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrglb $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), - VRRC:$vB, VMRGLB_shuffle_mask))]>; + [(set VRRC:$vD, (vmrglb_shuffle VRRC:$vA, VRRC:$vB))]>; def VMRGLH : VXForm_1<332, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrglh $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), - VRRC:$vB, VMRGLH_shuffle_mask))]>; + [(set VRRC:$vD, (vmrglh_shuffle VRRC:$vA, VRRC:$vB))]>; def VMRGLW : VXForm_1<396, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrglw $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), - VRRC:$vB, VMRGLW_shuffle_mask))]>; + [(set VRRC:$vD, (vmrglw_shuffle VRRC:$vA, VRRC:$vB))]>; def VMSUMMBM : VA1a_Int<37, "vmsummbm", int_ppc_altivec_vmsummbm>; def VMSUMSHM : VA1a_Int<40, "vmsumshm", int_ppc_altivec_vmsumshm>; @@ -440,16 +455,16 @@ def VSPLTB : VXForm_1<524, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), "vspltb $vD, $vB, $UIMM", VecPerm, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef), - VSPLTB_shuffle_mask:$UIMM))]>; + [(set VRRC:$vD, + (vspltb_shuffle:$UIMM (v16i8 VRRC:$vB), (undef)))]>; def VSPLTH : VXForm_1<588, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), "vsplth $vD, $vB, $UIMM", VecPerm, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef), - VSPLTH_shuffle_mask:$UIMM))]>; + [(set VRRC:$vD, + (vsplth_shuffle:$UIMM (v16i8 VRRC:$vB), (undef)))]>; def VSPLTW : VXForm_1<652, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), "vspltw $vD, $vB, $UIMM", VecPerm, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef), - VSPLTW_shuffle_mask:$UIMM))]>; + [(set VRRC:$vD, + (vspltw_shuffle:$UIMM (v16i8 VRRC:$vB), (undef)))]>; def VSR : VX1_Int< 708, "vsr" , int_ppc_altivec_vsr>; def VSRO : VX1_Int<1100, "vsro" , int_ppc_altivec_vsro>; @@ -479,13 +494,13 @@ def VPKSWUS : VX1_Int<334, "vpkswus", int_ppc_altivec_vpkswus>; def VPKUHUM : VXForm_1<14, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vpkuhum $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), - VRRC:$vB, VPKUHUM_shuffle_mask))]>; + [(set VRRC:$vD, + (vpkuhum_shuffle (v16i8 VRRC:$vA), VRRC:$vB))]>; def VPKUHUS : VX1_Int<142, "vpkuhus", int_ppc_altivec_vpkuhus>; def VPKUWUM : VXForm_1<78, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vpkuwum $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), - VRRC:$vB, VPKUWUM_shuffle_mask))]>; + [(set VRRC:$vD, + (vpkuwum_shuffle (v16i8 VRRC:$vA), VRRC:$vB))]>; def VPKUWUS : VX1_Int<206, "vpkuwus", int_ppc_altivec_vpkuwus>; // Vector Unpack. @@ -603,25 +618,25 @@ // Shuffles. // Match vsldoi(x,x), vpkuwum(x,x), vpkuhum(x,x) -def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VSLDOI_unary_shuffle_mask:$in), - (VSLDOI VRRC:$vA, VRRC:$vA, VSLDOI_unary_shuffle_mask:$in)>; -def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef,VPKUWUM_unary_shuffle_mask:$in), +def:Pat<(vsldoi_unary_shuffle:$in (v16i8 VRRC:$vA), undef), + (VSLDOI VRRC:$vA, VRRC:$vA, (VSLDOI_unary_get_imm VRRC:$in))>; +def:Pat<(vpkuwum_unary_shuffle (v16i8 VRRC:$vA), undef), (VPKUWUM VRRC:$vA, VRRC:$vA)>; -def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef,VPKUHUM_unary_shuffle_mask:$in), +def:Pat<(vpkuhum_unary_shuffle (v16i8 VRRC:$vA), undef), (VPKUHUM VRRC:$vA, VRRC:$vA)>; // Match vmrg*(x,x) -def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGLB_unary_shuffle_mask:$in), +def:Pat<(vmrglb_unary_shuffle (v16i8 VRRC:$vA), undef), (VMRGLB VRRC:$vA, VRRC:$vA)>; -def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGLH_unary_shuffle_mask:$in), +def:Pat<(vmrglh_unary_shuffle (v16i8 VRRC:$vA), undef), (VMRGLH VRRC:$vA, VRRC:$vA)>; -def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGLW_unary_shuffle_mask:$in), +def:Pat<(vmrglw_unary_shuffle (v16i8 VRRC:$vA), undef), (VMRGLW VRRC:$vA, VRRC:$vA)>; -def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHB_unary_shuffle_mask:$in), +def:Pat<(vmrghb_unary_shuffle (v16i8 VRRC:$vA), undef), (VMRGHB VRRC:$vA, VRRC:$vA)>; -def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHH_unary_shuffle_mask:$in), +def:Pat<(vmrghh_unary_shuffle (v16i8 VRRC:$vA), undef), (VMRGHH VRRC:$vA, VRRC:$vA)>; -def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHW_unary_shuffle_mask:$in), +def:Pat<(vmrghw_unary_shuffle (v16i8 VRRC:$vA), undef), (VMRGHW VRRC:$vA, VRRC:$vA)>; // Logical Operations Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Thu Apr 23 22:42:54 2009 @@ -45,7 +45,8 @@ DisableMMX("disable-mmx", cl::Hidden, cl::desc("Disable use of MMX")); // Forward declarations. -static SDValue getMOVLMask(unsigned NumElems, SelectionDAG &DAG, DebugLoc dl); +static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1, + SDValue V2); X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) : TargetLowering(TM) { @@ -1667,9 +1668,7 @@ // Special case: passing MMX values in XMM registers. Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, Arg); Arg = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2i64, Arg); - Arg = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v2i64, - DAG.getUNDEF(MVT::v2i64), Arg, - getMOVLMask(2, DAG, dl)); + Arg = getMOVL(DAG, dl, MVT::v2i64, DAG.getUNDEF(MVT::v2i64), Arg); break; } } @@ -2138,186 +2137,156 @@ } } -/// isUndefOrInRange - Op is either an undef node or a ConstantSDNode. Return -/// true if Op is undef or if its value falls within the specified range (L, H]. -static bool isUndefOrInRange(SDValue Op, unsigned Low, unsigned Hi) { - if (Op.getOpcode() == ISD::UNDEF) - return true; - - unsigned Val = cast(Op)->getZExtValue(); - return (Val >= Low && Val < Hi); +/// isUndefOrInRange - Return true if Val is undef or if its value falls within +/// the specified range (L, H]. +static bool isUndefOrInRange(int Val, int Low, int Hi) { + return (Val < 0) || (Val >= Low && Val < Hi); } -/// isUndefOrEqual - Op is either an undef node or a ConstantSDNode. Return -/// true if Op is undef or if its value equal to the specified value. -static bool isUndefOrEqual(SDValue Op, unsigned Val) { - if (Op.getOpcode() == ISD::UNDEF) +/// isUndefOrEqual - Val is either less than zero (undef) or equal to the +/// specified value. +static bool isUndefOrEqual(int Val, int CmpVal) { + if (Val < 0 || Val == CmpVal) return true; - return cast(Op)->getZExtValue() == Val; + return false; } -/// isPSHUFDMask - Return true if the specified VECTOR_SHUFFLE operand -/// specifies a shuffle of elements that is suitable for input to PSHUFD. -bool X86::isPSHUFDMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - if (N->getNumOperands() != 2 && N->getNumOperands() != 4) - return false; - - // Check if the value doesn't reference the second vector. - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) continue; - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - if (cast(Arg)->getZExtValue() >= e) - return false; - } - - return true; +/// isPSHUFDMask - Return true if the node specifies a shuffle of elements that +/// is suitable for input to PSHUFD or PSHUFW. That is, it doesn't reference +/// the second operand. +static bool isPSHUFDMask(const int *Mask, MVT VT) { + if (VT == MVT::v4f32 || VT == MVT::v4i32 || VT == MVT::v4i16) + return (Mask[0] < 4 && Mask[1] < 4 && Mask[2] < 4 && Mask[3] < 4); + if (VT == MVT::v2f64 || VT == MVT::v2i64) + return (Mask[0] < 2 && Mask[1] < 2); + return false; } -/// isPSHUFHWMask - Return true if the specified VECTOR_SHUFFLE operand -/// specifies a shuffle of elements that is suitable for input to PSHUFHW. -bool X86::isPSHUFHWMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); +bool X86::isPSHUFDMask(ShuffleVectorSDNode *N) { + return ::isPSHUFDMask(N->getMask(), N->getValueType(0)); +} - if (N->getNumOperands() != 8) +/// isPSHUFHWMask - Return true if the node specifies a shuffle of elements that +/// is suitable for input to PSHUFHW. +static bool isPSHUFHWMask(const int *Mask, MVT VT) { + if (VT != MVT::v8i16) return false; - - // Lower quadword copied in order. - for (unsigned i = 0; i != 4; ++i) { - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) continue; - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - if (cast(Arg)->getZExtValue() != i) + + // Lower quadword copied in order or undef. + for (int i = 0; i != 4; ++i) + if (Mask[i] >= 0 && Mask[i] != i) return false; - } - + // Upper quadword shuffled. - for (unsigned i = 4; i != 8; ++i) { - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) continue; - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - unsigned Val = cast(Arg)->getZExtValue(); - if (Val < 4 || Val > 7) + for (int i = 4; i != 8; ++i) + if (Mask[i] >= 0 && (Mask[i] < 4 || Mask[i] > 7)) return false; - } - + return true; } -/// isPSHUFLWMask - Return true if the specified VECTOR_SHUFFLE operand -/// specifies a shuffle of elements that is suitable for input to PSHUFLW. -bool X86::isPSHUFLWMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); +bool X86::isPSHUFHWMask(ShuffleVectorSDNode *N) { + return ::isPSHUFHWMask(N->getMask(), N->getValueType(0)); +} - if (N->getNumOperands() != 8) +/// isPSHUFLWMask - Return true if the node specifies a shuffle of elements that +/// is suitable for input to PSHUFLW. +static bool isPSHUFLWMask(const int *Mask, MVT VT) { + if (VT != MVT::v8i16) return false; - + // Upper quadword copied in order. - for (unsigned i = 4; i != 8; ++i) - if (!isUndefOrEqual(N->getOperand(i), i)) + for (int i = 4; i != 8; ++i) + if (Mask[i] >= 0 && Mask[i] != i) return false; - + // Lower quadword shuffled. - for (unsigned i = 0; i != 4; ++i) - if (!isUndefOrInRange(N->getOperand(i), 0, 4)) + for (int i = 0; i != 4; ++i) + if (Mask[i] >= 4) return false; - + return true; } +bool X86::isPSHUFLWMask(ShuffleVectorSDNode *N) { + return ::isPSHUFLWMask(N->getMask(), N->getValueType(0)); +} + /// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to SHUFP*. -template -static bool isSHUFPMask(SDOperand *Elems, unsigned NumElems) { - if (NumElems != 2 && NumElems != 4) return false; - - unsigned Half = NumElems / 2; - for (unsigned i = 0; i < Half; ++i) - if (!isUndefOrInRange(Elems[i], 0, NumElems)) +static bool isSHUFPMask(const int *Mask, MVT VT) { + int NumElems = VT.getVectorNumElements(); + if (NumElems != 2 && NumElems != 4) + return false; + + int Half = NumElems / 2; + for (int i = 0; i < Half; ++i) + if (!isUndefOrInRange(Mask[i], 0, NumElems)) return false; - for (unsigned i = Half; i < NumElems; ++i) - if (!isUndefOrInRange(Elems[i], NumElems, NumElems*2)) + for (int i = Half; i < NumElems; ++i) + if (!isUndefOrInRange(Mask[i], NumElems, NumElems*2)) return false; - + return true; } -bool X86::isSHUFPMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - return ::isSHUFPMask(N->op_begin(), N->getNumOperands()); +bool X86::isSHUFPMask(ShuffleVectorSDNode *N) { + return ::isSHUFPMask(N->getMask(), N->getValueType(0)); } /// isCommutedSHUFP - Returns true if the shuffle mask is exactly /// the reverse of what x86 shuffles want. x86 shuffles requires the lower /// half elements to come from vector 1 (which would equal the dest.) and /// the upper half to come from vector 2. -template -static bool isCommutedSHUFP(SDOperand *Ops, unsigned NumOps) { - if (NumOps != 2 && NumOps != 4) return false; - - unsigned Half = NumOps / 2; - for (unsigned i = 0; i < Half; ++i) - if (!isUndefOrInRange(Ops[i], NumOps, NumOps*2)) +static bool isCommutedSHUFPMask(const int *Mask, MVT VT) { + int NumElems = VT.getVectorNumElements(); + + if (NumElems != 2 && NumElems != 4) + return false; + + int Half = NumElems / 2; + for (int i = 0; i < Half; ++i) + if (!isUndefOrInRange(Mask[i], NumElems, NumElems*2)) return false; - for (unsigned i = Half; i < NumOps; ++i) - if (!isUndefOrInRange(Ops[i], 0, NumOps)) + for (int i = Half; i < NumElems; ++i) + if (!isUndefOrInRange(Mask[i], 0, NumElems)) return false; return true; } -static bool isCommutedSHUFP(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - return isCommutedSHUFP(N->op_begin(), N->getNumOperands()); +static bool isCommutedSHUFP(ShuffleVectorSDNode *N) { + return isCommutedSHUFPMask(N->getMask(), N->getValueType(0)); } /// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVHLPS. -bool X86::isMOVHLPSMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - if (N->getNumOperands() != 4) +bool X86::isMOVHLPSMask(ShuffleVectorSDNode *N) { + if (N->getValueType(0).getVectorNumElements() != 4) return false; // Expect bit0 == 6, bit1 == 7, bit2 == 2, bit3 == 3 - return isUndefOrEqual(N->getOperand(0), 6) && - isUndefOrEqual(N->getOperand(1), 7) && - isUndefOrEqual(N->getOperand(2), 2) && - isUndefOrEqual(N->getOperand(3), 3); -} - -/// isMOVHLPS_v_undef_Mask - Special case of isMOVHLPSMask for canonical form -/// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef, -/// <2, 3, 2, 3> -bool X86::isMOVHLPS_v_undef_Mask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - if (N->getNumOperands() != 4) - return false; - - // Expect bit0 == 2, bit1 == 3, bit2 == 2, bit3 == 3 - return isUndefOrEqual(N->getOperand(0), 2) && - isUndefOrEqual(N->getOperand(1), 3) && - isUndefOrEqual(N->getOperand(2), 2) && - isUndefOrEqual(N->getOperand(3), 3); + const int *Mask = N->getMask(); + return isUndefOrEqual(Mask[0], 6) && + isUndefOrEqual(Mask[1], 7) && + isUndefOrEqual(Mask[2], 2) && + isUndefOrEqual(Mask[3], 3); } /// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVLP{S|D}. -bool X86::isMOVLPMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); +bool X86::isMOVLPMask(ShuffleVectorSDNode *N) { + unsigned NumElems = N->getValueType(0).getVectorNumElements(); - unsigned NumElems = N->getNumOperands(); if (NumElems != 2 && NumElems != 4) return false; + const int *Mask = N->getMask(); for (unsigned i = 0; i < NumElems/2; ++i) - if (!isUndefOrEqual(N->getOperand(i), i + NumElems)) + if (!isUndefOrEqual(Mask[i], i + NumElems)) return false; for (unsigned i = NumElems/2; i < NumElems; ++i) - if (!isUndefOrEqual(N->getOperand(i), i)) + if (!isUndefOrEqual(Mask[i], i)) return false; return true; @@ -2326,37 +2295,49 @@ /// isMOVHPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVHP{S|D} /// and MOVLHPS. -bool X86::isMOVHPMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); +bool X86::isMOVHPMask(ShuffleVectorSDNode *N) { + unsigned NumElems = N->getValueType(0).getVectorNumElements(); - unsigned NumElems = N->getNumOperands(); if (NumElems != 2 && NumElems != 4) return false; + const int *Mask = N->getMask(); for (unsigned i = 0; i < NumElems/2; ++i) - if (!isUndefOrEqual(N->getOperand(i), i)) + if (!isUndefOrEqual(Mask[i], i)) return false; - for (unsigned i = 0; i < NumElems/2; ++i) { - SDValue Arg = N->getOperand(i + NumElems/2); - if (!isUndefOrEqual(Arg, i + NumElems)) + for (unsigned i = 0; i < NumElems/2; ++i) + if (!isUndefOrEqual(Mask[i + NumElems/2], i + NumElems)) return false; - } return true; } +/// isMOVHLPS_v_undef_Mask - Special case of isMOVHLPSMask for canonical form +/// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef, +/// <2, 3, 2, 3> +bool X86::isMOVHLPS_v_undef_Mask(ShuffleVectorSDNode *N) { + unsigned NumElems = N->getValueType(0).getVectorNumElements(); + + if (NumElems != 4) + return false; + + // Expect bit0 == 2, bit1 == 3, bit2 == 2, bit3 == 3 + const int *Mask = N->getMask(); + return isUndefOrEqual(Mask[0], 2) && isUndefOrEqual(Mask[1], 3) && + isUndefOrEqual(Mask[2], 2) && isUndefOrEqual(Mask[3], 3); +} + /// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKL. -template -bool static isUNPCKLMask(SDOperand *Elts, unsigned NumElts, - bool V2IsSplat = false) { +static bool isUNPCKLMask(const int *Mask, MVT VT, bool V2IsSplat = false) { + int NumElts = VT.getVectorNumElements(); if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) return false; - - for (unsigned i = 0, j = 0; i != NumElts; i += 2, ++j) { - SDValue BitI = Elts[i]; - SDValue BitI1 = Elts[i+1]; + + for (int i = 0, j = 0; i != NumElts; i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; if (!isUndefOrEqual(BitI, j)) return false; if (V2IsSplat) { @@ -2367,26 +2348,23 @@ return false; } } - return true; } -bool X86::isUNPCKLMask(SDNode *N, bool V2IsSplat) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - return ::isUNPCKLMask(N->op_begin(), N->getNumOperands(), V2IsSplat); +bool X86::isUNPCKLMask(ShuffleVectorSDNode *N, bool V2IsSplat) { + return ::isUNPCKLMask(N->getMask(), N->getValueType(0), V2IsSplat); } /// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKH. -template -bool static isUNPCKHMask(SDOperand *Elts, unsigned NumElts, - bool V2IsSplat = false) { +static bool isUNPCKHMask(const int *Mask, MVT VT, bool V2IsSplat = false) { + int NumElts = VT.getVectorNumElements(); if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) return false; - - for (unsigned i = 0, j = 0; i != NumElts; i += 2, ++j) { - SDValue BitI = Elts[i]; - SDValue BitI1 = Elts[i+1]; + + for (int i = 0, j = 0; i != NumElts; i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; if (!isUndefOrEqual(BitI, j + NumElts/2)) return false; if (V2IsSplat) { @@ -2397,270 +2375,166 @@ return false; } } - return true; } -bool X86::isUNPCKHMask(SDNode *N, bool V2IsSplat) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - return ::isUNPCKHMask(N->op_begin(), N->getNumOperands(), V2IsSplat); +bool X86::isUNPCKHMask(ShuffleVectorSDNode *N, bool V2IsSplat) { + return ::isUNPCKHMask(N->getMask(), N->getValueType(0), V2IsSplat); } /// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form /// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef, /// <0, 0, 1, 1> -bool X86::isUNPCKL_v_undef_Mask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - unsigned NumElems = N->getNumOperands(); +static bool isUNPCKL_v_undef_Mask(const int *Mask, MVT VT) { + int NumElems = VT.getVectorNumElements(); if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16) return false; - - for (unsigned i = 0, j = 0; i != NumElems; i += 2, ++j) { - SDValue BitI = N->getOperand(i); - SDValue BitI1 = N->getOperand(i+1); - + + for (int i = 0, j = 0; i != NumElems; i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; if (!isUndefOrEqual(BitI, j)) return false; if (!isUndefOrEqual(BitI1, j)) return false; } - return true; } +bool X86::isUNPCKL_v_undef_Mask(ShuffleVectorSDNode *N) { + return ::isUNPCKL_v_undef_Mask(N->getMask(), N->getValueType(0)); +} + /// isUNPCKH_v_undef_Mask - Special case of isUNPCKHMask for canonical form /// of vector_shuffle v, v, <2, 6, 3, 7>, i.e. vector_shuffle v, undef, /// <2, 2, 3, 3> -bool X86::isUNPCKH_v_undef_Mask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - unsigned NumElems = N->getNumOperands(); +static bool isUNPCKH_v_undef_Mask(const int *Mask, MVT VT) { + int NumElems = VT.getVectorNumElements(); if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16) return false; - - for (unsigned i = 0, j = NumElems / 2; i != NumElems; i += 2, ++j) { - SDValue BitI = N->getOperand(i); - SDValue BitI1 = N->getOperand(i + 1); - + + for (int i = 0, j = NumElems / 2; i != NumElems; i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; if (!isUndefOrEqual(BitI, j)) return false; if (!isUndefOrEqual(BitI1, j)) return false; } - return true; } +bool X86::isUNPCKH_v_undef_Mask(ShuffleVectorSDNode *N) { + return ::isUNPCKH_v_undef_Mask(N->getMask(), N->getValueType(0)); +} + /// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSS, /// MOVSD, and MOVD, i.e. setting the lowest element. -template -static bool isMOVLMask(SDOperand *Elts, unsigned NumElts) { +static bool isMOVLMask(const int *Mask, MVT VT) { + int NumElts = VT.getVectorNumElements(); if (NumElts != 2 && NumElts != 4) return false; - - if (!isUndefOrEqual(Elts[0], NumElts)) + + if (!isUndefOrEqual(Mask[0], NumElts)) return false; - - for (unsigned i = 1; i < NumElts; ++i) { - if (!isUndefOrEqual(Elts[i], i)) + + for (int i = 1; i < NumElts; ++i) + if (!isUndefOrEqual(Mask[i], i)) return false; - } - + return true; } -bool X86::isMOVLMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - return ::isMOVLMask(N->op_begin(), N->getNumOperands()); +bool X86::isMOVLMask(ShuffleVectorSDNode *N) { + return ::isMOVLMask(N->getMask(), N->getValueType(0)); } /// isCommutedMOVL - Returns true if the shuffle mask is except the reverse /// of what x86 movss want. X86 movs requires the lowest element to be lowest /// element of vector 2 and the other elements to come from vector 1 in order. -template -static bool isCommutedMOVL(SDOperand *Ops, unsigned NumOps, - bool V2IsSplat = false, - bool V2IsUndef = false) { +static bool isCommutedMOVLMask(const int *Mask, MVT VT, bool V2IsSplat = false, + bool V2IsUndef = false) { + int NumOps = VT.getVectorNumElements(); if (NumOps != 2 && NumOps != 4 && NumOps != 8 && NumOps != 16) return false; - - if (!isUndefOrEqual(Ops[0], 0)) + + if (!isUndefOrEqual(Mask[0], 0)) return false; - - for (unsigned i = 1; i < NumOps; ++i) { - SDValue Arg = Ops[i]; - if (!(isUndefOrEqual(Arg, i+NumOps) || - (V2IsUndef && isUndefOrInRange(Arg, NumOps, NumOps*2)) || - (V2IsSplat && isUndefOrEqual(Arg, NumOps)))) + + for (int i = 1; i < NumOps; ++i) + if (!(isUndefOrEqual(Mask[i], i+NumOps) || + (V2IsUndef && isUndefOrInRange(Mask[i], NumOps, NumOps*2)) || + (V2IsSplat && isUndefOrEqual(Mask[i], NumOps)))) return false; - } - + return true; } -static bool isCommutedMOVL(SDNode *N, bool V2IsSplat = false, +static bool isCommutedMOVL(ShuffleVectorSDNode *N, bool V2IsSplat = false, bool V2IsUndef = false) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - return isCommutedMOVL(N->op_begin(), N->getNumOperands(), - V2IsSplat, V2IsUndef); + return isCommutedMOVLMask(N->getMask(), N->getValueType(0), V2IsSplat, + V2IsUndef); } /// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSHDUP. -bool X86::isMOVSHDUPMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - if (N->getNumOperands() != 4) +bool X86::isMOVSHDUPMask(ShuffleVectorSDNode *N) { + if (N->getValueType(0).getVectorNumElements() != 4) return false; // Expect 1, 1, 3, 3 - for (unsigned i = 0; i < 2; ++i) { - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) continue; - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - unsigned Val = cast(Arg)->getZExtValue(); - if (Val != 1) return false; - } + const int *Mask = N->getMask(); + for (unsigned i = 0; i < 2; ++i) + if (Mask[i] >=0 && Mask[i] != 1) + return false; bool HasHi = false; for (unsigned i = 2; i < 4; ++i) { - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) continue; - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - unsigned Val = cast(Arg)->getZExtValue(); - if (Val != 3) return false; - HasHi = true; + if (Mask[i] >= 0 && Mask[i] != 3) + return false; + if (Mask[i] == 3) + HasHi = true; } - // Don't use movshdup if it can be done with a shufps. + // FIXME: verify that matching u, u, 3, 3 is what we want. return HasHi; } /// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSLDUP. -bool X86::isMOVSLDUPMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - if (N->getNumOperands() != 4) +bool X86::isMOVSLDUPMask(ShuffleVectorSDNode *N) { + if (N->getValueType(0).getVectorNumElements() != 4) return false; // Expect 0, 0, 2, 2 - for (unsigned i = 0; i < 2; ++i) { - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) continue; - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - unsigned Val = cast(Arg)->getZExtValue(); - if (Val != 0) return false; - } + const int *Mask = N->getMask(); + for (unsigned i = 0; i < 2; ++i) + if (Mask[i] > 0) + return false; bool HasHi = false; for (unsigned i = 2; i < 4; ++i) { - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) continue; - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - unsigned Val = cast(Arg)->getZExtValue(); - if (Val != 2) return false; - HasHi = true; - } - - // Don't use movshdup if it can be done with a shufps. - return HasHi; -} - -/// isIdentityMask - Return true if the specified VECTOR_SHUFFLE operand -/// specifies a identity operation on the LHS or RHS. -static bool isIdentityMask(SDNode *N, bool RHS = false) { - unsigned NumElems = N->getNumOperands(); - for (unsigned i = 0; i < NumElems; ++i) - if (!isUndefOrEqual(N->getOperand(i), i + (RHS ? NumElems : 0))) + if (Mask[i] >= 0 && Mask[i] != 2) return false; - return true; -} - -/// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand specifies -/// a splat of a single element. -static bool isSplatMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - // This is a splat operation if each element of the permute is the same, and - // if the value doesn't reference the second vector. - unsigned NumElems = N->getNumOperands(); - SDValue ElementBase; - unsigned i = 0; - for (; i != NumElems; ++i) { - SDValue Elt = N->getOperand(i); - if (isa(Elt)) { - ElementBase = Elt; - break; - } + if (Mask[i] == 2) + HasHi = true; } - - if (!ElementBase.getNode()) - return false; - - for (; i != NumElems; ++i) { - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) continue; - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - if (Arg != ElementBase) return false; - } - - // Make sure it is a splat of the first vector operand. - return cast(ElementBase)->getZExtValue() < NumElems; -} - -/// getSplatMaskEltNo - Given a splat mask, return the index to the element -/// we want to splat. -static SDValue getSplatMaskEltNo(SDNode *N) { - assert(isSplatMask(N) && "Not a splat mask"); - unsigned NumElems = N->getNumOperands(); - SDValue ElementBase; - unsigned i = 0; - for (; i != NumElems; ++i) { - SDValue Elt = N->getOperand(i); - if (isa(Elt)) - return Elt; - } - assert(0 && " No splat value found!"); - return SDValue(); -} - - -/// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand specifies -/// a splat of a single element and it's a 2 or 4 element mask. -bool X86::isSplatMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - // We can only splat 64-bit, and 32-bit quantities with a single instruction. - if (N->getNumOperands() != 4 && N->getNumOperands() != 2) - return false; - return ::isSplatMask(N); -} - -/// isSplatLoMask - Return true if the specified VECTOR_SHUFFLE operand -/// specifies a splat of zero element. -bool X86::isSplatLoMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i) - if (!isUndefOrEqual(N->getOperand(i), 0)) - return false; - return true; + // Don't use movsldup if it can be done with a shufps. + return HasHi; } /// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVDDUP. -bool X86::isMOVDDUPMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - unsigned e = N->getNumOperands() / 2; - for (unsigned i = 0; i < e; ++i) - if (!isUndefOrEqual(N->getOperand(i), i)) +bool X86::isMOVDDUPMask(ShuffleVectorSDNode *N) { + int e = N->getValueType(0).getVectorNumElements() / 2; + const int *Mask = N->getMask(); + + for (int i = 0; i < e; ++i) + if (!isUndefOrEqual(Mask[i], i)) return false; - for (unsigned i = 0; i < e; ++i) - if (!isUndefOrEqual(N->getOperand(e+i), i)) + for (int i = 0; i < e; ++i) + if (!isUndefOrEqual(Mask[e+i], i)) return false; return true; } @@ -2669,20 +2543,20 @@ /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUF* and SHUFP* /// instructions. unsigned X86::getShuffleSHUFImmediate(SDNode *N) { - unsigned NumOperands = N->getNumOperands(); + ShuffleVectorSDNode *SVOp = cast(N); + int NumOperands = SVOp->getValueType(0).getVectorNumElements(); + const int *MaskP = SVOp->getMask(); + unsigned Shift = (NumOperands == 4) ? 2 : 1; unsigned Mask = 0; - for (unsigned i = 0; i < NumOperands; ++i) { - unsigned Val = 0; - SDValue Arg = N->getOperand(NumOperands-i-1); - if (Arg.getOpcode() != ISD::UNDEF) - Val = cast(Arg)->getZExtValue(); + for (int i = 0; i < NumOperands; ++i) { + int Val = MaskP[NumOperands-i-1]; + if (Val < 0) Val = 0; if (Val >= NumOperands) Val -= NumOperands; Mask |= Val; if (i != NumOperands - 1) Mask <<= Shift; } - return Mask; } @@ -2690,19 +2564,16 @@ /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUFHW /// instructions. unsigned X86::getShufflePSHUFHWImmediate(SDNode *N) { + const int *MaskP = cast(N)->getMask(); unsigned Mask = 0; // 8 nodes, but we only care about the last 4. for (unsigned i = 7; i >= 4; --i) { - unsigned Val = 0; - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() != ISD::UNDEF) { - Val = cast(Arg)->getZExtValue(); + int Val = MaskP[i]; + if (Val >= 0) Mask |= (Val - 4); - } if (i != 4) Mask <<= 2; } - return Mask; } @@ -2710,90 +2581,71 @@ /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUFLW /// instructions. unsigned X86::getShufflePSHUFLWImmediate(SDNode *N) { + const int *MaskP = cast(N)->getMask(); unsigned Mask = 0; // 8 nodes, but we only care about the first 4. for (int i = 3; i >= 0; --i) { - unsigned Val = 0; - SDValue Arg = N->getOperand(i); - if (Arg.getOpcode() != ISD::UNDEF) - Val = cast(Arg)->getZExtValue(); - Mask |= Val; + int Val = MaskP[i]; + if (Val >= 0) + Mask |= Val; if (i != 0) Mask <<= 2; } - return Mask; } -/// CommuteVectorShuffle - Swap vector_shuffle operands as well as -/// values in ther permute mask. -static SDValue CommuteVectorShuffle(SDValue Op, SDValue &V1, - SDValue &V2, SDValue &Mask, - SelectionDAG &DAG) { - MVT VT = Op.getValueType(); - MVT MaskVT = Mask.getValueType(); - MVT EltVT = MaskVT.getVectorElementType(); - unsigned NumElems = Mask.getNumOperands(); - SmallVector MaskVec; - DebugLoc dl = Op.getDebugLoc(); - - for (unsigned i = 0; i != NumElems; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) { - MaskVec.push_back(DAG.getUNDEF(EltVT)); - continue; - } - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - unsigned Val = cast(Arg)->getZExtValue(); - if (Val < NumElems) - MaskVec.push_back(DAG.getConstant(Val + NumElems, EltVT)); +/// CommuteVectorShuffle - Swap vector_shuffle operands as well as values in +/// their permute mask. +static SDValue CommuteVectorShuffle(ShuffleVectorSDNode *SVOp, + SelectionDAG &DAG) { + MVT VT = SVOp->getValueType(0); + int NumElems = VT.getVectorNumElements(); + const int *Mask = SVOp->getMask(); + SmallVector MaskVec; + + for (int i = 0; i != NumElems; ++i) { + int idx = Mask[i]; + if (idx < 0) + MaskVec.push_back(idx); + else if (idx < NumElems) + MaskVec.push_back(idx + NumElems); else - MaskVec.push_back(DAG.getConstant(Val - NumElems, EltVT)); + MaskVec.push_back(idx - NumElems); } - - std::swap(V1, V2); - Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, &MaskVec[0], NumElems); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, Mask); + return DAG.getVectorShuffle(VT, SVOp->getDebugLoc(), SVOp->getOperand(1), + SVOp->getOperand(0), &MaskVec[0]); } /// CommuteVectorShuffleMask - Change values in a shuffle permute mask assuming /// the two vector operands have swapped position. -static -SDValue CommuteVectorShuffleMask(SDValue Mask, SelectionDAG &DAG, DebugLoc dl) { - MVT MaskVT = Mask.getValueType(); - MVT EltVT = MaskVT.getVectorElementType(); - unsigned NumElems = Mask.getNumOperands(); - SmallVector MaskVec; - for (unsigned i = 0; i != NumElems; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) { - MaskVec.push_back(DAG.getUNDEF(EltVT)); +static void CommuteVectorShuffleMask(SmallVectorImpl &Mask, MVT VT) { + int NumElems = VT.getVectorNumElements(); + for (int i = 0; i != NumElems; ++i) { + int idx = Mask[i]; + if (idx < 0) continue; - } - assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - unsigned Val = cast(Arg)->getZExtValue(); - if (Val < NumElems) - MaskVec.push_back(DAG.getConstant(Val + NumElems, EltVT)); + else if (idx < NumElems) + Mask[i] = idx + NumElems; else - MaskVec.push_back(DAG.getConstant(Val - NumElems, EltVT)); + Mask[i] = idx - NumElems; } - return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, &MaskVec[0], NumElems); } - /// ShouldXformToMOVHLPS - Return true if the node should be transformed to /// match movhlps. The lower half elements should come from upper half of /// V1 (and in order), and the upper half elements should come from the upper /// half of V2 (and in order). -static bool ShouldXformToMOVHLPS(SDNode *Mask) { - unsigned NumElems = Mask->getNumOperands(); +static bool ShouldXformToMOVHLPS(ShuffleVectorSDNode *Op) { + int NumElems = Op->getValueType(0).getVectorNumElements(); + const int *Mask = Op->getMask(); + if (NumElems != 4) return false; for (unsigned i = 0, e = 2; i != e; ++i) - if (!isUndefOrEqual(Mask->getOperand(i), i+2)) + if (!isUndefOrEqual(Mask[i], i+2)) return false; for (unsigned i = 2; i != 4; ++i) - if (!isUndefOrEqual(Mask->getOperand(i), i+4)) + if (!isUndefOrEqual(Mask[i], i+4)) return false; return true; } @@ -2817,7 +2669,8 @@ /// V1 (and in order), and the upper half elements should come from the upper /// half of V2 (and in order). And since V1 will become the source of the /// MOVLP, it must be either a vector load or a scalar load to vector. -static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2, SDNode *Mask) { +static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2, + ShuffleVectorSDNode *Op) { if (!ISD::isNON_EXTLoad(V1) && !isScalarLoadToVector(V1)) return false; // Is V2 is a vector load, don't do this transformation. We will try to use @@ -2825,14 +2678,16 @@ if (ISD::isNON_EXTLoad(V2)) return false; - unsigned NumElems = Mask->getNumOperands(); + int NumElems = Op->getValueType(0).getVectorNumElements(); + const int *Mask = Op->getMask(); + if (NumElems != 2 && NumElems != 4) return false; - for (unsigned i = 0, e = NumElems/2; i != e; ++i) - if (!isUndefOrEqual(Mask->getOperand(i), i)) + for (int i = 0, e = NumElems/2; i != e; ++i) + if (!isUndefOrEqual(Mask[i], i)) return false; - for (unsigned i = NumElems/2; i != NumElems; ++i) - if (!isUndefOrEqual(Mask->getOperand(i), i+NumElems)) + for (int i = NumElems/2; i != NumElems; ++i) + if (!isUndefOrEqual(Mask[i], i+NumElems)) return false; return true; } @@ -2850,29 +2705,6 @@ return true; } -/// isUndefShuffle - Returns true if N is a VECTOR_SHUFFLE that can be resolved -/// to an undef. -static bool isUndefShuffle(SDNode *N) { - if (N->getOpcode() != ISD::VECTOR_SHUFFLE) - return false; - - SDValue V1 = N->getOperand(0); - SDValue V2 = N->getOperand(1); - SDValue Mask = N->getOperand(2); - unsigned NumElems = Mask.getNumOperands(); - for (unsigned i = 0; i != NumElems; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() != ISD::UNDEF) { - unsigned Val = cast(Arg)->getZExtValue(); - if (Val < NumElems && V1.getOpcode() != ISD::UNDEF) - return false; - else if (Val >= NumElems && V2.getOpcode() != ISD::UNDEF) - return false; - } - } - return true; -} - /// isZeroNode - Returns true if Elt is a constant zero or a floating point /// constant +0.0. static inline bool isZeroNode(SDValue Elt) { @@ -2883,34 +2715,26 @@ } /// isZeroShuffle - Returns true if N is a VECTOR_SHUFFLE that can be resolved -/// to an zero vector. -static bool isZeroShuffle(SDNode *N) { - if (N->getOpcode() != ISD::VECTOR_SHUFFLE) - return false; - +/// to an zero vector. +/// FIXME: move to dag combiner? +static bool isZeroShuffle(ShuffleVectorSDNode *N) { SDValue V1 = N->getOperand(0); SDValue V2 = N->getOperand(1); - SDValue Mask = N->getOperand(2); - unsigned NumElems = Mask.getNumOperands(); - for (unsigned i = 0; i != NumElems; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() == ISD::UNDEF) - continue; - - unsigned Idx = cast(Arg)->getZExtValue(); - if (Idx < NumElems) { - unsigned Opc = V1.getNode()->getOpcode(); - if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V1.getNode())) + const int *Mask = N->getMask(); + int NumElems = N->getValueType(0).getVectorNumElements(); + for (int i = 0; i != NumElems; ++i) { + int Idx = Mask[i]; + if (Idx >= NumElems) { + unsigned Opc = V2.getOpcode(); + if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V2.getNode())) continue; - if (Opc != ISD::BUILD_VECTOR || - !isZeroNode(V1.getNode()->getOperand(Idx))) + if (Opc != ISD::BUILD_VECTOR || !isZeroNode(V2.getOperand(Idx-NumElems))) return false; - } else if (Idx >= NumElems) { - unsigned Opc = V2.getNode()->getOpcode(); - if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V2.getNode())) + } else if (Idx >= 0) { + unsigned Opc = V1.getOpcode(); + if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V1.getNode())) continue; - if (Opc != ISD::BUILD_VECTOR || - !isZeroNode(V2.getNode()->getOperand(Idx - NumElems))) + if (Opc != ISD::BUILD_VECTOR || !isZeroNode(V1.getOperand(Idx))) return false; } } @@ -2958,127 +2782,94 @@ /// NormalizeMask - V2 is a splat, modify the mask (if needed) so all elements /// that point to V2 points to its first element. -static SDValue NormalizeMask(SDValue Mask, SelectionDAG &DAG) { - assert(Mask.getOpcode() == ISD::BUILD_VECTOR); - +static SDValue NormalizeMask(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { + MVT VT = SVOp->getValueType(0); + int NumElems = VT.getVectorNumElements(); + const int *Mask = SVOp->getMask(); + bool Changed = false; - SmallVector MaskVec; - unsigned NumElems = Mask.getNumOperands(); - for (unsigned i = 0; i != NumElems; ++i) { - SDValue Arg = Mask.getOperand(i); - if (Arg.getOpcode() != ISD::UNDEF) { - unsigned Val = cast(Arg)->getZExtValue(); - if (Val > NumElems) { - Arg = DAG.getConstant(NumElems, Arg.getValueType()); - Changed = true; - } + SmallVector MaskVec; + + for (int i = 0; i != NumElems; ++i) { + int idx = Mask[i]; + if (idx > NumElems) { + idx = NumElems; + Changed = true; } - MaskVec.push_back(Arg); + MaskVec.push_back(idx); } - if (Changed) - Mask = DAG.getNode(ISD::BUILD_VECTOR, Mask.getDebugLoc(), - Mask.getValueType(), - &MaskVec[0], MaskVec.size()); - return Mask; + return DAG.getVectorShuffle(VT, SVOp->getDebugLoc(), SVOp->getOperand(0), + SVOp->getOperand(1), &MaskVec[0]); + return SDValue(SVOp, 0); } /// getMOVLMask - Returns a vector_shuffle mask for an movs{s|d}, movd /// operation of specified width. -static SDValue getMOVLMask(unsigned NumElems, SelectionDAG &DAG, DebugLoc dl) { - MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); - MVT BaseVT = MaskVT.getVectorElementType(); - - SmallVector MaskVec; - MaskVec.push_back(DAG.getConstant(NumElems, BaseVT)); +static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1, + SDValue V2) { + unsigned NumElems = VT.getVectorNumElements(); + SmallVector Mask; + Mask.push_back(NumElems); for (unsigned i = 1; i != NumElems; ++i) - MaskVec.push_back(DAG.getConstant(i, BaseVT)); - return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskVec[0], MaskVec.size()); + Mask.push_back(i); + return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]); } -/// getUnpacklMask - Returns a vector_shuffle mask for an unpackl operation -/// of specified width. -static SDValue getUnpacklMask(unsigned NumElems, SelectionDAG &DAG, - DebugLoc dl) { - MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); - MVT BaseVT = MaskVT.getVectorElementType(); - SmallVector MaskVec; +/// getUnpackl - Returns a vector_shuffle node for an unpackl operation. +static SDValue getUnpackl(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1, + SDValue V2) { + unsigned NumElems = VT.getVectorNumElements(); + SmallVector Mask; for (unsigned i = 0, e = NumElems/2; i != e; ++i) { - MaskVec.push_back(DAG.getConstant(i, BaseVT)); - MaskVec.push_back(DAG.getConstant(i + NumElems, BaseVT)); + Mask.push_back(i); + Mask.push_back(i + NumElems); } - return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskVec[0], MaskVec.size()); + return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]); } -/// getUnpackhMask - Returns a vector_shuffle mask for an unpackh operation -/// of specified width. -static SDValue getUnpackhMask(unsigned NumElems, SelectionDAG &DAG, - DebugLoc dl) { - MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); - MVT BaseVT = MaskVT.getVectorElementType(); +/// getUnpackhMask - Returns a vector_shuffle node for an unpackh operation. +static SDValue getUnpackh(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1, + SDValue V2) { + unsigned NumElems = VT.getVectorNumElements(); unsigned Half = NumElems/2; - SmallVector MaskVec; + SmallVector Mask; for (unsigned i = 0; i != Half; ++i) { - MaskVec.push_back(DAG.getConstant(i + Half, BaseVT)); - MaskVec.push_back(DAG.getConstant(i + NumElems + Half, BaseVT)); + Mask.push_back(i + Half); + Mask.push_back(i + NumElems + Half); } - return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskVec[0], MaskVec.size()); -} - -/// getSwapEltZeroMask - Returns a vector_shuffle mask for a shuffle that swaps -/// element #0 of a vector with the specified index, leaving the rest of the -/// elements in place. -static SDValue getSwapEltZeroMask(unsigned NumElems, unsigned DestElt, - SelectionDAG &DAG, DebugLoc dl) { - MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); - MVT BaseVT = MaskVT.getVectorElementType(); - SmallVector MaskVec; - // Element #0 of the result gets the elt we are replacing. - MaskVec.push_back(DAG.getConstant(DestElt, BaseVT)); - for (unsigned i = 1; i != NumElems; ++i) - MaskVec.push_back(DAG.getConstant(i == DestElt ? 0 : i, BaseVT)); - return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskVec[0], MaskVec.size()); + return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]); } /// PromoteSplat - Promote a splat of v4f32, v8i16 or v16i8 to v4i32. -static SDValue PromoteSplat(SDValue Op, SelectionDAG &DAG, bool HasSSE2) { - MVT PVT = HasSSE2 ? MVT::v4i32 : MVT::v4f32; - MVT VT = Op.getValueType(); - if (PVT == VT) - return Op; - SDValue V1 = Op.getOperand(0); - SDValue Mask = Op.getOperand(2); - unsigned MaskNumElems = Mask.getNumOperands(); - unsigned NumElems = MaskNumElems; - DebugLoc dl = Op.getDebugLoc(); - // Special handling of v4f32 -> v4i32. - if (VT != MVT::v4f32) { - // Find which element we want to splat. - SDNode* EltNoNode = getSplatMaskEltNo(Mask.getNode()).getNode(); - unsigned EltNo = cast(EltNoNode)->getZExtValue(); - // unpack elements to the correct location - while (NumElems > 4) { - if (EltNo < NumElems/2) { - Mask = getUnpacklMask(MaskNumElems, DAG, dl); - } else { - Mask = getUnpackhMask(MaskNumElems, DAG, dl); - EltNo -= NumElems/2; - } - V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V1, Mask); - NumElems >>= 1; +static SDValue PromoteSplat(ShuffleVectorSDNode *SV, SelectionDAG &DAG, + bool HasSSE2) { + if (SV->getValueType(0).getVectorNumElements() <= 4) + return SDValue(SV, 0); + + MVT PVT = MVT::v4f32; + MVT VT = SV->getValueType(0); + DebugLoc dl = SV->getDebugLoc(); + SDValue V1 = SV->getOperand(0); + int NumElems = VT.getVectorNumElements(); + int EltNo = SV->getSplatIndex(); + + // unpack elements to the correct location + while (NumElems > 4) { + if (EltNo < NumElems/2) { + V1 = getUnpackl(DAG, dl, VT, V1, V1); + } else { + V1 = getUnpackh(DAG, dl, VT, V1, V1); + EltNo -= NumElems/2; } - SDValue Cst = DAG.getConstant(EltNo, MVT::i32); - Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Cst, Cst, Cst, Cst); + NumElems >>= 1; } - + + // Perform the splat. + int SplatMask[4] = { EltNo, EltNo, EltNo, EltNo }; V1 = DAG.getNode(ISD::BIT_CONVERT, dl, PVT, V1); - SDValue Shuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, PVT, V1, - DAG.getUNDEF(PVT), Mask); - return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Shuffle); + V1 = DAG.getVectorShuffle(PVT, dl, V1, DAG.getUNDEF(PVT), &SplatMask[0]); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, V1); } /// isVectorLoad - Returns true if the node is a vector load, a scalar @@ -3095,32 +2886,28 @@ /// CanonicalizeMovddup - Cannonicalize movddup shuffle to v2f64. /// -static SDValue CanonicalizeMovddup(SDValue Op, SDValue V1, SDValue Mask, - SelectionDAG &DAG, bool HasSSE3) { +static SDValue CanonicalizeMovddup(ShuffleVectorSDNode *SV, SelectionDAG &DAG, + bool HasSSE3) { // If we have sse3 and shuffle has more than one use or input is a load, then // use movddup. Otherwise, use movlhps. - bool UseMovddup = HasSSE3 && (!Op.hasOneUse() || isVectorLoad(V1)); + SDValue V1 = SV->getOperand(0); + + bool UseMovddup = HasSSE3 && (!SV->hasOneUse() || isVectorLoad(V1)); MVT PVT = UseMovddup ? MVT::v2f64 : MVT::v4f32; - MVT VT = Op.getValueType(); + MVT VT = SV->getValueType(0); if (VT == PVT) - return Op; - DebugLoc dl = Op.getDebugLoc(); - unsigned NumElems = PVT.getVectorNumElements(); - if (NumElems == 2) { - SDValue Cst = DAG.getTargetConstant(0, MVT::i32); - Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i32, Cst, Cst); + return SDValue(SV, 0); + + DebugLoc dl = SV->getDebugLoc(); + V1 = DAG.getNode(ISD::BIT_CONVERT, dl, PVT, V1); + if (PVT.getVectorNumElements() == 2) { + int Mask[2] = { 0, 0 }; + V1 = DAG.getVectorShuffle(PVT, dl, V1, DAG.getUNDEF(PVT), Mask); } else { - assert(NumElems == 4); - SDValue Cst0 = DAG.getTargetConstant(0, MVT::i32); - SDValue Cst1 = DAG.getTargetConstant(1, MVT::i32); - Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, - Cst0, Cst1, Cst0, Cst1); + int Mask[4] = { 0, 1, 0, 1 }; + V1 = DAG.getVectorShuffle(PVT, dl, V1, DAG.getUNDEF(PVT), Mask); } - - V1 = DAG.getNode(ISD::BIT_CONVERT, dl, PVT, V1); - SDValue Shuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, PVT, V1, - DAG.getUNDEF(PVT), Mask); - return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Shuffle); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, V1); } /// getShuffleVectorZeroOrUndef - Return a vector_shuffle of the specified @@ -3130,39 +2917,31 @@ static SDValue getShuffleVectorZeroOrUndef(SDValue V2, unsigned Idx, bool isZero, bool HasSSE2, SelectionDAG &DAG) { - DebugLoc dl = V2.getDebugLoc(); MVT VT = V2.getValueType(); SDValue V1 = isZero - ? getZeroVector(VT, HasSSE2, DAG, dl) : DAG.getUNDEF(VT); - unsigned NumElems = V2.getValueType().getVectorNumElements(); - MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); - MVT EVT = MaskVT.getVectorElementType(); - SmallVector MaskVec; + ? getZeroVector(VT, HasSSE2, DAG, V2.getDebugLoc()) : DAG.getUNDEF(VT); + unsigned NumElems = VT.getVectorNumElements(); + SmallVector MaskVec; for (unsigned i = 0; i != NumElems; ++i) - if (i == Idx) // If this is the insertion idx, put the low elt of V2 here. - MaskVec.push_back(DAG.getConstant(NumElems, EVT)); - else - MaskVec.push_back(DAG.getConstant(i, EVT)); - SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskVec[0], MaskVec.size()); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, Mask); + // If this is the insertion idx, put the low elt of V2 here. + MaskVec.push_back(i == Idx ? NumElems : i); + return DAG.getVectorShuffle(VT, V2.getDebugLoc(), V1, V2, &MaskVec[0]); } /// getNumOfConsecutiveZeros - Return the number of elements in a result of /// a shuffle that is zero. static -unsigned getNumOfConsecutiveZeros(SDValue Op, SDValue Mask, - unsigned NumElems, bool Low, - SelectionDAG &DAG) { +unsigned getNumOfConsecutiveZeros(ShuffleVectorSDNode *SVOp, const int *Mask, + int NumElems, bool Low, SelectionDAG &DAG) { unsigned NumZeros = 0; - for (unsigned i = 0; i < NumElems; ++i) { + for (int i = 0; i < NumElems; ++i) { unsigned Index = Low ? i : NumElems-i-1; - SDValue Idx = Mask.getOperand(Index); - if (Idx.getOpcode() == ISD::UNDEF) { + int Idx = Mask[Index]; + if (Idx < 0) { ++NumZeros; continue; } - SDValue Elt = DAG.getShuffleScalarElt(Op.getNode(), Index); + SDValue Elt = DAG.getShuffleScalarElt(SVOp, Index); if (Elt.getNode() && isZeroNode(Elt)) ++NumZeros; else @@ -3173,40 +2952,40 @@ /// isVectorShift - Returns true if the shuffle can be implemented as a /// logical left or right shift of a vector. -static bool isVectorShift(SDValue Op, SDValue Mask, SelectionDAG &DAG, +/// FIXME: split into pslldqi, psrldqi, palignr variants. +static bool isVectorShift(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG, bool &isLeft, SDValue &ShVal, unsigned &ShAmt) { - unsigned NumElems = Mask.getNumOperands(); + const int *Mask = SVOp->getMask(); + int NumElems = SVOp->getValueType(0).getVectorNumElements(); isLeft = true; - unsigned NumZeros= getNumOfConsecutiveZeros(Op, Mask, NumElems, true, DAG); + unsigned NumZeros = getNumOfConsecutiveZeros(SVOp, Mask, NumElems, true, DAG); if (!NumZeros) { isLeft = false; - NumZeros = getNumOfConsecutiveZeros(Op, Mask, NumElems, false, DAG); + NumZeros = getNumOfConsecutiveZeros(SVOp, Mask, NumElems, false, DAG); if (!NumZeros) return false; } - bool SeenV1 = false; bool SeenV2 = false; - for (unsigned i = NumZeros; i < NumElems; ++i) { - unsigned Val = isLeft ? (i - NumZeros) : i; - SDValue Idx = Mask.getOperand(isLeft ? i : (i - NumZeros)); - if (Idx.getOpcode() == ISD::UNDEF) + for (int i = NumZeros; i < NumElems; ++i) { + int Val = isLeft ? (i - NumZeros) : i; + int Idx = Mask[isLeft ? i : (i - NumZeros)]; + if (Idx < 0) continue; - unsigned Index = cast(Idx)->getZExtValue(); - if (Index < NumElems) + if (Idx < NumElems) SeenV1 = true; else { - Index -= NumElems; + Idx -= NumElems; SeenV2 = true; } - if (Index != Val) + if (Idx != Val) return false; } if (SeenV1 && SeenV2) return false; - ShVal = SeenV1 ? Op.getOperand(0) : Op.getOperand(1); + ShVal = SeenV1 ? SVOp->getOperand(0) : SVOp->getOperand(1); ShAmt = NumZeros; return true; } @@ -3291,8 +3070,8 @@ /// getVShift - Return a vector logical shift node. /// static SDValue getVShift(bool isLeft, MVT VT, SDValue SrcOp, - unsigned NumBits, SelectionDAG &DAG, - const TargetLowering &TLI, DebugLoc dl) { + unsigned NumBits, SelectionDAG &DAG, + const TargetLowering &TLI, DebugLoc dl) { bool isMMX = VT.getSizeInBits() == 64; MVT ShVT = isMMX ? MVT::v1i64 : MVT::v2i64; unsigned Opc = isLeft ? X86ISD::VSHL : X86ISD::VSRL; @@ -3377,11 +3156,13 @@ // Now we have our 32-bit value zero extended in the low element of // a vector. If Idx != 0, swizzle it into place. if (Idx != 0) { - SDValue Ops[] = { - Item, DAG.getUNDEF(Item.getValueType()), - getSwapEltZeroMask(VecElts, Idx, DAG, dl) - }; - Item = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VecVT, Ops, 3); + SmallVector Mask; + Mask.push_back(Idx); + for (unsigned i = 1; i != VecElts; ++i) + Mask.push_back(i); + Item = DAG.getVectorShuffle(VecVT, dl, Item, + DAG.getUNDEF(Item.getValueType()), + &Mask[0]); } return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Item); } @@ -3425,15 +3206,10 @@ // Turn it into a shuffle of zero and zero-extended scalar to vector. Item = getShuffleVectorZeroOrUndef(Item, 0, NumZero > 0, Subtarget->hasSSE2(), DAG); - MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); - MVT MaskEVT = MaskVT.getVectorElementType(); - SmallVector MaskVec; + SmallVector MaskVec; for (unsigned i = 0; i < NumElems; i++) - MaskVec.push_back(DAG.getConstant((i == Idx) ? 0 : 1, MaskEVT)); - SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskVec[0], MaskVec.size()); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, Item, - DAG.getUNDEF(VT), Mask); + MaskVec.push_back(i == Idx ? 0 : 1); + return DAG.getVectorShuffle(VT, dl, Item, DAG.getUNDEF(VT), &MaskVec[0]); } } @@ -3491,54 +3267,48 @@ V[i] = V[i*2]; // Must be a zero vector. break; case 1: - V[i] = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[i*2+1], V[i*2], - getMOVLMask(NumElems, DAG, dl)); + V[i] = getMOVL(DAG, dl, VT, V[i*2+1], V[i*2]); break; case 2: - V[i] = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[i*2], V[i*2+1], - getMOVLMask(NumElems, DAG, dl)); + V[i] = getMOVL(DAG, dl, VT, V[i*2], V[i*2+1]); break; case 3: - V[i] = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[i*2], V[i*2+1], - getUnpacklMask(NumElems, DAG, dl)); + V[i] = getUnpackl(DAG, dl, VT, V[i*2], V[i*2+1]); break; } } - MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); - MVT EVT = MaskVT.getVectorElementType(); - SmallVector MaskVec; + SmallVector MaskVec; bool Reverse = (NonZeros & 0x3) == 2; for (unsigned i = 0; i < 2; ++i) - if (Reverse) - MaskVec.push_back(DAG.getConstant(1-i, EVT)); - else - MaskVec.push_back(DAG.getConstant(i, EVT)); + MaskVec.push_back(Reverse ? 1-i : i); Reverse = ((NonZeros & (0x3 << 2)) >> 2) == 2; for (unsigned i = 0; i < 2; ++i) - if (Reverse) - MaskVec.push_back(DAG.getConstant(1-i+NumElems, EVT)); - else - MaskVec.push_back(DAG.getConstant(i+NumElems, EVT)); - SDValue ShufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskVec[0], MaskVec.size()); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[0], V[1], ShufMask); + MaskVec.push_back(Reverse ? 1-i+NumElems : i+NumElems); + return DAG.getVectorShuffle(VT, dl, V[0], V[1], &MaskVec[0]); } if (Values.size() > 2) { + // If we have SSE 4.1, Expand into a number of inserts. + if (getSubtarget()->hasSSE41()) { + V[0] = DAG.getUNDEF(VT); + for (unsigned i = 0; i < NumElems; ++i) + if (Op.getOperand(i).getOpcode() != ISD::UNDEF) + V[0] = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, VT, V[0], + Op.getOperand(i), DAG.getIntPtrConstant(i)); + return V[0]; + } // Expand into a number of unpckl*. // e.g. for v4f32 // Step 1: unpcklps 0, 2 ==> X: // : unpcklps 1, 3 ==> Y: // Step 2: unpcklps X, Y ==> <3, 2, 1, 0> - SDValue UnpckMask = getUnpacklMask(NumElems, DAG, dl); for (unsigned i = 0; i < NumElems; ++i) V[i] = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Op.getOperand(i)); NumElems >>= 1; while (NumElems != 0) { for (unsigned i = 0; i < NumElems; ++i) - V[i] = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[i], V[i + NumElems], - UnpckMask); + V[i] = getUnpackl(DAG, dl, VT, V[i], V[i + NumElems]); NumElems >>= 1; } return V[0]; @@ -3553,11 +3323,12 @@ // 3. [ssse3] 2 x pshufb + 1 x por // 4. [all] mov + pshuflw + pshufhw + N x (pextrw + pinsrw) static -SDValue LowerVECTOR_SHUFFLEv8i16(SDValue V1, SDValue V2, - SDValue PermMask, SelectionDAG &DAG, - X86TargetLowering &TLI, DebugLoc dl) { - SmallVector MaskElts(PermMask.getNode()->op_begin(), - PermMask.getNode()->op_end()); +SDValue LowerVECTOR_SHUFFLEv8i16(ShuffleVectorSDNode *SVOp, + SelectionDAG &DAG, X86TargetLowering &TLI) { + SDValue V1 = SVOp->getOperand(0); + SDValue V2 = SVOp->getOperand(1); + DebugLoc dl = SVOp->getDebugLoc(); + const int *Mask = SVOp->getMask(); SmallVector MaskVals; // Determine if more than 1 of the words in each of the low and high quadwords @@ -3568,9 +3339,7 @@ BitVector InputQuads(4); for (unsigned i = 0; i < 8; ++i) { SmallVectorImpl &Quad = i < 4 ? LoQuad : HiQuad; - SDValue Elt = MaskElts[i]; - int EltIdx = Elt.getOpcode() == ISD::UNDEF ? -1 : - cast(Elt)->getZExtValue(); + int EltIdx = Mask[i]; MaskVals.push_back(EltIdx); if (EltIdx < 0) { ++Quad[0]; @@ -3623,14 +3392,12 @@ // words from all 4 input quadwords. SDValue NewV; if (BestLoQuad >= 0 || BestHiQuad >= 0) { - SmallVector MaskV; - MaskV.push_back(DAG.getConstant(BestLoQuad < 0 ? 0 : BestLoQuad, MVT::i64)); - MaskV.push_back(DAG.getConstant(BestHiQuad < 0 ? 1 : BestHiQuad, MVT::i64)); - SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64, &MaskV[0], 2); - - NewV = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v2i64, - DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V1), - DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V2), Mask); + SmallVector MaskV; + MaskV.push_back(BestLoQuad < 0 ? 0 : BestLoQuad); + MaskV.push_back(BestHiQuad < 0 ? 1 : BestHiQuad); + NewV = DAG.getVectorShuffle(MVT::v2i64, dl, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V1), + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V2), &MaskV[0]); NewV = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, NewV); // Rewrite the MaskVals and assign NewV to V1 if NewV now contains all the @@ -3668,15 +3435,8 @@ // If we've eliminated the use of V2, and the new mask is a pshuflw or // pshufhw, that's as cheap as it gets. Return the new shuffle. if ((pshufhw && InOrder[0]) || (pshuflw && InOrder[1])) { - MaskV.clear(); - for (unsigned i = 0; i != 8; ++i) - MaskV.push_back((MaskVals[i] < 0) ? DAG.getUNDEF(MVT::i16) - : DAG.getConstant(MaskVals[i], - MVT::i16)); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v8i16, NewV, - DAG.getUNDEF(MVT::v8i16), - DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v8i16, - &MaskV[0], 8)); + return DAG.getVectorShuffle(MVT::v8i16, dl, NewV, + DAG.getUNDEF(MVT::v8i16), &MaskVals[0]); } } @@ -3733,49 +3493,45 @@ // and update MaskVals with new element order. BitVector InOrder(8); if (BestLoQuad >= 0) { - SmallVector MaskV; + SmallVector MaskV; for (int i = 0; i != 4; ++i) { int idx = MaskVals[i]; if (idx < 0) { - MaskV.push_back(DAG.getUNDEF(MVT::i16)); + MaskV.push_back(-1); InOrder.set(i); } else if ((idx / 4) == BestLoQuad) { - MaskV.push_back(DAG.getConstant(idx & 3, MVT::i16)); + MaskV.push_back(idx & 3); InOrder.set(i); } else { - MaskV.push_back(DAG.getUNDEF(MVT::i16)); + MaskV.push_back(-1); } } for (unsigned i = 4; i != 8; ++i) - MaskV.push_back(DAG.getConstant(i, MVT::i16)); - NewV = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v8i16, NewV, - DAG.getUNDEF(MVT::v8i16), - DAG.getNode(ISD::BUILD_VECTOR, dl, - MVT::v8i16, &MaskV[0], 8)); + MaskV.push_back(i); + NewV = DAG.getVectorShuffle(MVT::v8i16, dl, NewV, DAG.getUNDEF(MVT::v8i16), + &MaskV[0]); } // If BestHi >= 0, generate a pshufhw to put the high elements in order, // and update MaskVals with the new element order. if (BestHiQuad >= 0) { - SmallVector MaskV; + SmallVector MaskV; for (unsigned i = 0; i != 4; ++i) - MaskV.push_back(DAG.getConstant(i, MVT::i16)); + MaskV.push_back(i); for (unsigned i = 4; i != 8; ++i) { int idx = MaskVals[i]; if (idx < 0) { - MaskV.push_back(DAG.getUNDEF(MVT::i16)); + MaskV.push_back(-1); InOrder.set(i); } else if ((idx / 4) == BestHiQuad) { - MaskV.push_back(DAG.getConstant((idx & 3) + 4, MVT::i16)); + MaskV.push_back((idx & 3) + 4); InOrder.set(i); } else { - MaskV.push_back(DAG.getUNDEF(MVT::i16)); + MaskV.push_back(-1); } } - NewV = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v8i16, NewV, - DAG.getUNDEF(MVT::v8i16), - DAG.getNode(ISD::BUILD_VECTOR, dl, - MVT::v8i16, &MaskV[0], 8)); + NewV = DAG.getVectorShuffle(MVT::v8i16, dl, NewV, DAG.getUNDEF(MVT::v8i16), + &MaskV[0]); } // In case BestHi & BestLo were both -1, which means each quadword has a word @@ -3811,11 +3567,12 @@ // 2. [ssse3] 2 x pshufb + 1 x por // 3. [all] v8i16 shuffle + N x pextrw + rotate + pinsrw static -SDValue LowerVECTOR_SHUFFLEv16i8(SDValue V1, SDValue V2, - SDValue PermMask, SelectionDAG &DAG, - X86TargetLowering &TLI, DebugLoc dl) { - SmallVector MaskElts(PermMask.getNode()->op_begin(), - PermMask.getNode()->op_end()); +SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp, + SelectionDAG &DAG, X86TargetLowering &TLI) { + SDValue V1 = SVOp->getOperand(0); + SDValue V2 = SVOp->getOperand(1); + DebugLoc dl = SVOp->getDebugLoc(); + const int *Mask = SVOp->getMask(); SmallVector MaskVals; // If we have SSSE3, case 1 is generated when all result bytes come from @@ -3825,9 +3582,7 @@ bool V1Only = true; bool V2Only = true; for (unsigned i = 0; i < 16; ++i) { - SDValue Elt = MaskElts[i]; - int EltIdx = Elt.getOpcode() == ISD::UNDEF ? -1 : - cast(Elt)->getZExtValue(); + int EltIdx = Mask[i]; MaskVals.push_back(EltIdx); if (EltIdx < 0) continue; @@ -3958,11 +3713,14 @@ /// the right sequence. e.g. /// vector_shuffle <>, <>, < 3, 4, | 10, 11, | 0, 1, | 14, 15> static -SDValue RewriteAsNarrowerShuffle(SDValue V1, SDValue V2, - MVT VT, - SDValue PermMask, SelectionDAG &DAG, - TargetLowering &TLI, DebugLoc dl) { - unsigned NumElems = PermMask.getNumOperands(); +SDValue RewriteAsNarrowerShuffle(ShuffleVectorSDNode *SVOp, + SelectionDAG &DAG, + TargetLowering &TLI, DebugLoc dl) { + MVT VT = SVOp->getValueType(0); + SDValue V1 = SVOp->getOperand(0); + SDValue V2 = SVOp->getOperand(1); + const int *PermMask = SVOp->getMask(); + unsigned NumElems = VT.getVectorNumElements(); unsigned NewWidth = (NumElems == 4) ? 2 : 4; MVT MaskVT = MVT::getIntVectorWithNumElements(NewWidth); MVT MaskEltVT = MaskVT.getVectorElementType(); @@ -3981,38 +3739,35 @@ else NewVT = MVT::v2f64; } - unsigned Scale = NumElems / NewWidth; - SmallVector MaskVec; + int Scale = NumElems / NewWidth; + SmallVector MaskVec; for (unsigned i = 0; i < NumElems; i += Scale) { - unsigned StartIdx = ~0U; - for (unsigned j = 0; j < Scale; ++j) { - SDValue Elt = PermMask.getOperand(i+j); - if (Elt.getOpcode() == ISD::UNDEF) + int StartIdx = -1; + for (int j = 0; j < Scale; ++j) { + int EltIdx = PermMask[i+j]; + if (EltIdx < 0) continue; - unsigned EltIdx = cast(Elt)->getZExtValue(); - if (StartIdx == ~0U) + if (StartIdx == -1) StartIdx = EltIdx - (EltIdx % Scale); if (EltIdx != StartIdx + j) return SDValue(); } - if (StartIdx == ~0U) - MaskVec.push_back(DAG.getUNDEF(MaskEltVT)); + if (StartIdx == -1) + MaskVec.push_back(-1); else - MaskVec.push_back(DAG.getConstant(StartIdx / Scale, MaskEltVT)); + MaskVec.push_back(StartIdx / Scale); } V1 = DAG.getNode(ISD::BIT_CONVERT, dl, NewVT, V1); V2 = DAG.getNode(ISD::BIT_CONVERT, dl, NewVT, V2); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, NewVT, V1, V2, - DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskVec[0], MaskVec.size())); + return DAG.getVectorShuffle(NewVT, dl, V1, V2, &MaskVec[0]); } /// getVZextMovL - Return a zero-extending vector move low node. /// static SDValue getVZextMovL(MVT VT, MVT OpVT, - SDValue SrcOp, SelectionDAG &DAG, - const X86Subtarget *Subtarget, DebugLoc dl) { + SDValue SrcOp, SelectionDAG &DAG, + const X86Subtarget *Subtarget, DebugLoc dl) { if (VT == MVT::v2f64 || VT == MVT::v4f32) { LoadSDNode *LD = NULL; if (!isScalarLoadToVector(SrcOp.getNode(), &LD)) @@ -4046,31 +3801,37 @@ /// LowerVECTOR_SHUFFLE_4wide - Handle all 4 wide cases with a number of /// shuffles. static SDValue -LowerVECTOR_SHUFFLE_4wide(SDValue V1, SDValue V2, - SDValue PermMask, MVT VT, SelectionDAG &DAG, - DebugLoc dl) { - MVT MaskVT = PermMask.getValueType(); - MVT MaskEVT = MaskVT.getVectorElementType(); +LowerVECTOR_SHUFFLE_4wide(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { + SDValue V1 = SVOp->getOperand(0); + SDValue V2 = SVOp->getOperand(1); + DebugLoc dl = SVOp->getDebugLoc(); + MVT VT = SVOp->getValueType(0); + const int *PermMaskPtr = SVOp->getMask(); + SmallVector, 8> Locs; Locs.resize(4); - SmallVector Mask1(4, DAG.getUNDEF(MaskEVT)); + SmallVector Mask1(4U, -1); + SmallVector PermMask; + + for (unsigned i = 0; i != 8; ++i) + PermMask.push_back(PermMaskPtr[i]); + unsigned NumHi = 0; unsigned NumLo = 0; for (unsigned i = 0; i != 4; ++i) { - SDValue Elt = PermMask.getOperand(i); - if (Elt.getOpcode() == ISD::UNDEF) { + int Idx = PermMask[i]; + if (Idx < 0) { Locs[i] = std::make_pair(-1, -1); } else { - unsigned Val = cast(Elt)->getZExtValue(); - assert(Val < 8 && "Invalid VECTOR_SHUFFLE index!"); - if (Val < 4) { + assert(Idx < 8 && "Invalid VECTOR_SHUFFLE index!"); + if (Idx < 4) { Locs[i] = std::make_pair(0, NumLo); - Mask1[NumLo] = Elt; + Mask1[NumLo] = Idx; NumLo++; } else { Locs[i] = std::make_pair(1, NumHi); if (2+NumHi < 4) - Mask1[2+NumHi] = Elt; + Mask1[2+NumHi] = Idx; NumHi++; } } @@ -4081,24 +3842,21 @@ // implemented with two shuffles. First shuffle gather the elements. // The second shuffle, which takes the first shuffle as both of its // vector operands, put the elements into the right order. - V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, - DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &Mask1[0], Mask1.size())); + V1 = DAG.getVectorShuffle(VT, dl, V1, V2, &Mask1[0]); - SmallVector Mask2(4, DAG.getUNDEF(MaskEVT)); + SmallVector Mask2(4U, -1); + for (unsigned i = 0; i != 4; ++i) { if (Locs[i].first == -1) continue; else { unsigned Idx = (i < 2) ? 0 : 4; Idx += Locs[i].first * 2 + Locs[i].second; - Mask2[i] = DAG.getConstant(Idx, MaskEVT); + Mask2[i] = Idx; } } - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V1, - DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &Mask2[0], Mask2.size())); + return DAG.getVectorShuffle(VT, dl, V1, V1, &Mask2[0]); } else if (NumLo == 3 || NumHi == 3) { // Otherwise, we must have three elements from one vector, call it X, and // one element from the other, call it Y. First, use a shufps to build an @@ -4109,60 +3867,51 @@ // from X. if (NumHi == 3) { // Normalize it so the 3 elements come from V1. - PermMask = CommuteVectorShuffleMask(PermMask, DAG, dl); + CommuteVectorShuffleMask(PermMask, VT); std::swap(V1, V2); } // Find the element from V2. unsigned HiIndex; for (HiIndex = 0; HiIndex < 3; ++HiIndex) { - SDValue Elt = PermMask.getOperand(HiIndex); - if (Elt.getOpcode() == ISD::UNDEF) + int Val = PermMask[HiIndex]; + if (Val < 0) continue; - unsigned Val = cast(Elt)->getZExtValue(); if (Val >= 4) break; } - Mask1[0] = PermMask.getOperand(HiIndex); - Mask1[1] = DAG.getUNDEF(MaskEVT); - Mask1[2] = PermMask.getOperand(HiIndex^1); - Mask1[3] = DAG.getUNDEF(MaskEVT); - V2 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, - DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, &Mask1[0], 4)); + Mask1[0] = PermMask[HiIndex]; + Mask1[1] = -1; + Mask1[2] = PermMask[HiIndex^1]; + Mask1[3] = -1; + V2 = DAG.getVectorShuffle(VT, dl, V1, V2, &Mask1[0]); if (HiIndex >= 2) { - Mask1[0] = PermMask.getOperand(0); - Mask1[1] = PermMask.getOperand(1); - Mask1[2] = DAG.getConstant(HiIndex & 1 ? 6 : 4, MaskEVT); - Mask1[3] = DAG.getConstant(HiIndex & 1 ? 4 : 6, MaskEVT); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, - DAG.getNode(ISD::BUILD_VECTOR, dl, - MaskVT, &Mask1[0], 4)); + Mask1[0] = PermMask[0]; + Mask1[1] = PermMask[1]; + Mask1[2] = HiIndex & 1 ? 6 : 4; + Mask1[3] = HiIndex & 1 ? 4 : 6; + return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask1[0]); } else { - Mask1[0] = DAG.getConstant(HiIndex & 1 ? 2 : 0, MaskEVT); - Mask1[1] = DAG.getConstant(HiIndex & 1 ? 0 : 2, MaskEVT); - Mask1[2] = PermMask.getOperand(2); - Mask1[3] = PermMask.getOperand(3); - if (Mask1[2].getOpcode() != ISD::UNDEF) - Mask1[2] = - DAG.getConstant(cast(Mask1[2])->getZExtValue()+4, - MaskEVT); - if (Mask1[3].getOpcode() != ISD::UNDEF) - Mask1[3] = - DAG.getConstant(cast(Mask1[3])->getZExtValue()+4, - MaskEVT); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V2, V1, - DAG.getNode(ISD::BUILD_VECTOR, dl, - MaskVT, &Mask1[0], 4)); + Mask1[0] = HiIndex & 1 ? 2 : 0; + Mask1[1] = HiIndex & 1 ? 0 : 2; + Mask1[2] = PermMask[2]; + Mask1[3] = PermMask[3]; + if (Mask1[2] >= 0) + Mask1[2] += 4; + if (Mask1[3] >= 0) + Mask1[3] += 4; + return DAG.getVectorShuffle(VT, dl, V2, V1, &Mask1[0]); } } // Break it into (shuffle shuffle_hi, shuffle_lo). Locs.clear(); - SmallVector LoMask(4, DAG.getUNDEF(MaskEVT)); - SmallVector HiMask(4, DAG.getUNDEF(MaskEVT)); - SmallVector *MaskPtr = &LoMask; + SmallVector LoMask(4U, -1); + SmallVector HiMask(4U, -1); + + SmallVector *MaskPtr = &LoMask; unsigned MaskIdx = 0; unsigned LoIdx = 0; unsigned HiIdx = 2; @@ -4173,84 +3922,68 @@ LoIdx = 0; HiIdx = 2; } - SDValue Elt = PermMask.getOperand(i); - if (Elt.getOpcode() == ISD::UNDEF) { + int Idx = PermMask[i]; + if (Idx < 0) { Locs[i] = std::make_pair(-1, -1); - } else if (cast(Elt)->getZExtValue() < 4) { + } else if (Idx < 4) { Locs[i] = std::make_pair(MaskIdx, LoIdx); - (*MaskPtr)[LoIdx] = Elt; + (*MaskPtr)[LoIdx] = Idx; LoIdx++; } else { Locs[i] = std::make_pair(MaskIdx, HiIdx); - (*MaskPtr)[HiIdx] = Elt; + (*MaskPtr)[HiIdx] = Idx; HiIdx++; } } - SDValue LoShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, - DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &LoMask[0], LoMask.size())); - SDValue HiShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, - DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &HiMask[0], HiMask.size())); - SmallVector MaskOps; + SDValue LoShuffle = DAG.getVectorShuffle(VT, dl, V1, V2, &LoMask[0]); + SDValue HiShuffle = DAG.getVectorShuffle(VT, dl, V1, V2, &HiMask[0]); + SmallVector MaskOps; for (unsigned i = 0; i != 4; ++i) { if (Locs[i].first == -1) { - MaskOps.push_back(DAG.getUNDEF(MaskEVT)); + MaskOps.push_back(-1); } else { unsigned Idx = Locs[i].first * 4 + Locs[i].second; - MaskOps.push_back(DAG.getConstant(Idx, MaskEVT)); + MaskOps.push_back(Idx); } } - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, LoShuffle, HiShuffle, - DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &MaskOps[0], MaskOps.size())); + return DAG.getVectorShuffle(VT, dl, LoShuffle, HiShuffle, &MaskOps[0]); } SDValue X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { + ShuffleVectorSDNode *SVOp = cast(Op); SDValue V1 = Op.getOperand(0); SDValue V2 = Op.getOperand(1); - SDValue PermMask = Op.getOperand(2); MVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); - unsigned NumElems = PermMask.getNumOperands(); + const int *PermMask = cast(Op.getNode())->getMask(); + unsigned NumElems = VT.getVectorNumElements(); bool isMMX = VT.getSizeInBits() == 64; bool V1IsUndef = V1.getOpcode() == ISD::UNDEF; bool V2IsUndef = V2.getOpcode() == ISD::UNDEF; bool V1IsSplat = false; bool V2IsSplat = false; - // FIXME: Check for legal shuffle and return? - - if (isUndefShuffle(Op.getNode())) - return DAG.getUNDEF(VT); - - if (isZeroShuffle(Op.getNode())) + if (isZeroShuffle(SVOp)) return getZeroVector(VT, Subtarget->hasSSE2(), DAG, dl); - if (isIdentityMask(PermMask.getNode())) - return V1; - else if (isIdentityMask(PermMask.getNode(), true)) - return V2; - // Canonicalize movddup shuffles. - if (V2IsUndef && Subtarget->hasSSE2() && - VT.getSizeInBits() == 128 && - X86::isMOVDDUPMask(PermMask.getNode())) - return CanonicalizeMovddup(Op, V1, PermMask, DAG, Subtarget->hasSSE3()); - - if (isSplatMask(PermMask.getNode())) { - if (isMMX || NumElems < 4) return Op; - // Promote it to a v4{if}32 splat. - return PromoteSplat(Op, DAG, Subtarget->hasSSE2()); + if (V2IsUndef && Subtarget->hasSSE2() && VT.getSizeInBits() == 128 && + X86::isMOVDDUPMask(SVOp)) + return CanonicalizeMovddup(SVOp, DAG, Subtarget->hasSSE3()); + + // Promote splats to v4f32. + if (SVOp->isSplat()) { + if (isMMX || NumElems < 4) + return Op; + return PromoteSplat(SVOp, DAG, Subtarget->hasSSE2()); } // If the shuffle can be profitably rewritten as a narrower shuffle, then // do it! if (VT == MVT::v8i16 || VT == MVT::v16i8) { - SDValue NewOp= RewriteAsNarrowerShuffle(V1, V2, VT, PermMask, DAG, - *this, dl); + SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, *this, dl); if (NewOp.getNode()) return DAG.getNode(ISD::BIT_CONVERT, dl, VT, LowerVECTOR_SHUFFLE(NewOp, DAG)); @@ -4258,32 +3991,29 @@ // FIXME: Figure out a cleaner way to do this. // Try to make use of movq to zero out the top part. if (ISD::isBuildVectorAllZeros(V2.getNode())) { - SDValue NewOp = RewriteAsNarrowerShuffle(V1, V2, VT, PermMask, - DAG, *this, dl); + SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, *this, dl); if (NewOp.getNode()) { - SDValue NewV1 = NewOp.getOperand(0); - SDValue NewV2 = NewOp.getOperand(1); - SDValue NewMask = NewOp.getOperand(2); - if (isCommutedMOVL(NewMask.getNode(), true, false)) { - NewOp = CommuteVectorShuffle(NewOp, NewV1, NewV2, NewMask, DAG); - return getVZextMovL(VT, NewOp.getValueType(), NewV2, DAG, Subtarget, - dl); - } + if (isCommutedMOVL(cast(NewOp), true, false)) + return getVZextMovL(VT, NewOp.getValueType(), NewOp.getOperand(0), + DAG, Subtarget, dl); } } else if (ISD::isBuildVectorAllZeros(V1.getNode())) { - SDValue NewOp= RewriteAsNarrowerShuffle(V1, V2, VT, PermMask, - DAG, *this, dl); - if (NewOp.getNode() && X86::isMOVLMask(NewOp.getOperand(2).getNode())) + SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, *this, dl); + if (NewOp.getNode() && X86::isMOVLMask(cast(NewOp))) return getVZextMovL(VT, NewOp.getValueType(), NewOp.getOperand(1), - DAG, Subtarget, dl); + DAG, Subtarget, dl); } } - + + if (X86::isPSHUFDMask(SVOp)) + return Op; + // Check if this can be converted into a logical shift. bool isLeft = false; unsigned ShAmt = 0; SDValue ShVal; - bool isShift = isVectorShift(Op, PermMask, DAG, isLeft, ShVal, ShAmt); + bool isShift = getSubtarget()->hasSSE2() && + isVectorShift(SVOp, DAG, isLeft, ShVal, ShAmt); if (isShift && ShVal.hasOneUse()) { // If the shifted value has multiple uses, it may be cheaper to use // v_set0 + movlhps or movhlps, etc. @@ -4291,8 +4021,8 @@ ShAmt *= EVT.getSizeInBits(); return getVShift(isLeft, VT, ShVal, ShAmt, DAG, *this, dl); } - - if (X86::isMOVLMask(PermMask.getNode())) { + + if (X86::isMOVLMask(SVOp)) { if (V1IsUndef) return V2; if (ISD::isBuildVectorAllZeros(V1.getNode())) @@ -4300,17 +4030,18 @@ if (!isMMX) return Op; } - - if (!isMMX && (X86::isMOVSHDUPMask(PermMask.getNode()) || - X86::isMOVSLDUPMask(PermMask.getNode()) || - X86::isMOVHLPSMask(PermMask.getNode()) || - X86::isMOVHPMask(PermMask.getNode()) || - X86::isMOVLPMask(PermMask.getNode()))) + + // FIXME: fold these into legal mask. + if (!isMMX && (X86::isMOVSHDUPMask(SVOp) || + X86::isMOVSLDUPMask(SVOp) || + X86::isMOVHLPSMask(SVOp) || + X86::isMOVHPMask(SVOp) || + X86::isMOVLPMask(SVOp))) return Op; - if (ShouldXformToMOVHLPS(PermMask.getNode()) || - ShouldXformToMOVLP(V1.getNode(), V2.getNode(), PermMask.getNode())) - return CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); + if (ShouldXformToMOVHLPS(SVOp) || + ShouldXformToMOVLP(V1.getNode(), V2.getNode(), SVOp)) + return CommuteVectorShuffle(SVOp, DAG); if (isShift) { // No better options. Use a vshl / vsrl. @@ -4318,7 +4049,7 @@ ShAmt *= EVT.getSizeInBits(); return getVShift(isLeft, VT, ShVal, ShAmt, DAG, *this, dl); } - + bool Commuted = false; // FIXME: This should also accept a bitcast of a splat? Be careful, not // 1,1,1,1 -> v8i16 though. @@ -4327,115 +4058,84 @@ // Canonicalize the splat or undef, if present, to be on the RHS. if ((V1IsSplat || V1IsUndef) && !(V2IsSplat || V2IsUndef)) { - Op = CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); + Op = CommuteVectorShuffle(SVOp, DAG); + SVOp = cast(Op); + V1 = SVOp->getOperand(0); + V2 = SVOp->getOperand(1); std::swap(V1IsSplat, V2IsSplat); std::swap(V1IsUndef, V2IsUndef); Commuted = true; } - // FIXME: Figure out a cleaner way to do this. - if (isCommutedMOVL(PermMask.getNode(), V2IsSplat, V2IsUndef)) { - if (V2IsUndef) return V1; - Op = CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); - if (V2IsSplat) { - // V2 is a splat, so the mask may be malformed. That is, it may point - // to any V2 element. The instruction selectior won't like this. Get - // a corrected mask and commute to form a proper MOVS{S|D}. - SDValue NewMask = getMOVLMask(NumElems, DAG, dl); - if (NewMask.getNode() != PermMask.getNode()) - Op = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, NewMask); - } - return Op; + if (isCommutedMOVL(SVOp, V2IsSplat, V2IsUndef)) { + // Shuffling low element of v1 into undef, just return v1. + if (V2IsUndef) + return V1; + // If V2 is a splat, the mask may be malformed such as <4,3,3,3>, which + // the instruction selector will not match, so get a canonical MOVL with + // swapped operands to undo the commute. + return getMOVL(DAG, dl, VT, V2, V1); } - if (X86::isUNPCKL_v_undef_Mask(PermMask.getNode()) || - X86::isUNPCKH_v_undef_Mask(PermMask.getNode()) || - X86::isUNPCKLMask(PermMask.getNode()) || - X86::isUNPCKHMask(PermMask.getNode())) + if (X86::isUNPCKL_v_undef_Mask(SVOp) || + X86::isUNPCKH_v_undef_Mask(SVOp) || + X86::isUNPCKLMask(SVOp) || + X86::isUNPCKHMask(SVOp)) return Op; if (V2IsSplat) { // Normalize mask so all entries that point to V2 points to its first // element then try to match unpck{h|l} again. If match, return a // new vector_shuffle with the corrected mask. - SDValue NewMask = NormalizeMask(PermMask, DAG); - if (NewMask.getNode() != PermMask.getNode()) { - if (X86::isUNPCKLMask(NewMask.getNode(), true)) { - SDValue NewMask = getUnpacklMask(NumElems, DAG, dl); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, NewMask); - } else if (X86::isUNPCKHMask(NewMask.getNode(), true)) { - SDValue NewMask = getUnpackhMask(NumElems, DAG, dl); - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, NewMask); + SDValue NewMask = NormalizeMask(SVOp, DAG); + ShuffleVectorSDNode *NSVOp = cast(NewMask); + if (NSVOp != SVOp) { + if (X86::isUNPCKLMask(NSVOp, true)) { + return NewMask; + } else if (X86::isUNPCKHMask(NSVOp, true)) { + return NewMask; } } } - // Normalize the node to match x86 shuffle ops if needed - if (V2.getOpcode() != ISD::UNDEF && isCommutedSHUFP(PermMask.getNode())) - Op = CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); - if (Commuted) { // Commute is back and try unpck* again. - Op = CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); - if (X86::isUNPCKL_v_undef_Mask(PermMask.getNode()) || - X86::isUNPCKH_v_undef_Mask(PermMask.getNode()) || - X86::isUNPCKLMask(PermMask.getNode()) || - X86::isUNPCKHMask(PermMask.getNode())) - return Op; + // FIXME: this seems wrong. + SDValue NewOp = CommuteVectorShuffle(SVOp, DAG); + ShuffleVectorSDNode *NewSVOp = cast(NewOp); + if (X86::isUNPCKL_v_undef_Mask(NewSVOp) || + X86::isUNPCKH_v_undef_Mask(NewSVOp) || + X86::isUNPCKLMask(NewSVOp) || + X86::isUNPCKHMask(NewSVOp)) + return NewOp; } // FIXME: for mmx, bitcast v2i32 to v4i16 for shuffle. - // Try PSHUF* first, then SHUFP*. - // MMX doesn't have PSHUFD but it does have PSHUFW. While it's theoretically - // possible to shuffle a v2i32 using PSHUFW, that's not yet implemented. - if (isMMX && NumElems == 4 && X86::isPSHUFDMask(PermMask.getNode())) { - if (V2.getOpcode() != ISD::UNDEF) - return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, - DAG.getUNDEF(VT), PermMask); - return Op; - } - - if (!isMMX) { - if (Subtarget->hasSSE2() && - (X86::isPSHUFDMask(PermMask.getNode()) || - X86::isPSHUFHWMask(PermMask.getNode()) || - X86::isPSHUFLWMask(PermMask.getNode()))) { - MVT RVT = VT; - if (VT == MVT::v4f32) { - RVT = MVT::v4i32; - Op = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, RVT, - DAG.getNode(ISD::BIT_CONVERT, dl, RVT, V1), - DAG.getUNDEF(RVT), PermMask); - } else if (V2.getOpcode() != ISD::UNDEF) - Op = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, RVT, V1, - DAG.getUNDEF(RVT), PermMask); - if (RVT != VT) - Op = DAG.getNode(ISD::BIT_CONVERT, dl, VT, Op); - return Op; - } - // Binary or unary shufps. - if (X86::isSHUFPMask(PermMask.getNode()) || - (V2.getOpcode() == ISD::UNDEF && X86::isPSHUFDMask(PermMask.getNode()))) - return Op; - } + // Normalize the node to match x86 shuffle ops if needed + if (!isMMX && V2.getOpcode() != ISD::UNDEF && isCommutedSHUFP(SVOp)) + return CommuteVectorShuffle(SVOp, DAG); + // Check for legal shuffle and return? + if (isShuffleMaskLegal(PermMask, VT)) + return Op; + // Handle v8i16 specifically since SSE can do byte extraction and insertion. if (VT == MVT::v8i16) { - SDValue NewOp = LowerVECTOR_SHUFFLEv8i16(V1, V2, PermMask, DAG, *this, dl); + SDValue NewOp = LowerVECTOR_SHUFFLEv8i16(SVOp, DAG, *this); if (NewOp.getNode()) return NewOp; } if (VT == MVT::v16i8) { - SDValue NewOp = LowerVECTOR_SHUFFLEv16i8(V1, V2, PermMask, DAG, *this, dl); + SDValue NewOp = LowerVECTOR_SHUFFLEv16i8(SVOp, DAG, *this); if (NewOp.getNode()) return NewOp; } // Handle all 4 wide cases with a number of shuffles except for MMX. if (NumElems == 4 && !isMMX) - return LowerVECTOR_SHUFFLE_4wide(V1, V2, PermMask, VT, DAG, dl); + return LowerVECTOR_SHUFFLE_4wide(SVOp, DAG); return SDValue(); } @@ -4529,22 +4229,12 @@ unsigned Idx = cast(Op.getOperand(1))->getZExtValue(); if (Idx == 0) return Op; + // SHUFPS the element to the lowest double word, then movss. - MVT MaskVT = MVT::getIntVectorWithNumElements(4); - SmallVector IdxVec; - IdxVec. - push_back(DAG.getConstant(Idx, MaskVT.getVectorElementType())); - IdxVec. - push_back(DAG.getUNDEF(MaskVT.getVectorElementType())); - IdxVec. - push_back(DAG.getUNDEF(MaskVT.getVectorElementType())); - IdxVec. - push_back(DAG.getUNDEF(MaskVT.getVectorElementType())); - SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &IdxVec[0], IdxVec.size()); - SDValue Vec = Op.getOperand(0); - Vec = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, Vec.getValueType(), - Vec, DAG.getUNDEF(Vec.getValueType()), Mask); + int Mask[4] = { Idx, -1, -1, -1 }; + MVT VVT = Op.getOperand(0).getValueType(); + SDValue Vec = DAG.getVectorShuffle(VVT, dl, Op.getOperand(0), + DAG.getUNDEF(VVT), Mask); return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, Vec, DAG.getIntPtrConstant(0)); } else if (VT.getSizeInBits() == 64) { @@ -4558,17 +4248,10 @@ // UNPCKHPD the element to the lowest double word, then movsd. // Note if the lower 64 bits of the result of the UNPCKHPD is then stored // to a f64mem, the whole operation is folded into a single MOVHPDmr. - MVT MaskVT = MVT::getIntVectorWithNumElements(2); - SmallVector IdxVec; - IdxVec.push_back(DAG.getConstant(1, MaskVT.getVectorElementType())); - IdxVec. - push_back(DAG.getUNDEF(MaskVT.getVectorElementType())); - SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, - &IdxVec[0], IdxVec.size()); - SDValue Vec = Op.getOperand(0); - Vec = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, Vec.getValueType(), - Vec, DAG.getUNDEF(Vec.getValueType()), - Mask); + int Mask[2] = { 1, -1 }; + MVT VVT = Op.getOperand(0).getValueType(); + SDValue Vec = DAG.getVectorShuffle(VVT, dl, Op.getOperand(0), + DAG.getUNDEF(VVT), Mask); return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, Vec, DAG.getIntPtrConstant(0)); } @@ -5075,19 +4758,6 @@ Constant *C1 = ConstantVector::get(CV1); SDValue CPIdx1 = DAG.getConstantPool(C1, getPointerTy(), 16); - SmallVector MaskVec; - MaskVec.push_back(DAG.getConstant(0, MVT::i32)); - MaskVec.push_back(DAG.getConstant(4, MVT::i32)); - MaskVec.push_back(DAG.getConstant(1, MVT::i32)); - MaskVec.push_back(DAG.getConstant(5, MVT::i32)); - SDValue UnpcklMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, - &MaskVec[0], MaskVec.size()); - SmallVector MaskVec2; - MaskVec2.push_back(DAG.getConstant(1, MVT::i32)); - MaskVec2.push_back(DAG.getConstant(0, MVT::i32)); - SDValue ShufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i32, - &MaskVec2[0], MaskVec2.size()); - SDValue XR1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v4i32, DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op.getOperand(0), @@ -5096,13 +4766,11 @@ DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op.getOperand(0), DAG.getIntPtrConstant(0))); - SDValue Unpck1 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v4i32, - XR1, XR2, UnpcklMask); + SDValue Unpck1 = getUnpackl(DAG, dl, MVT::v4i32, XR1, XR2); SDValue CLod0 = DAG.getLoad(MVT::v4i32, dl, DAG.getEntryNode(), CPIdx0, PseudoSourceValue::getConstantPool(), 0, false, 16); - SDValue Unpck2 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v4i32, - Unpck1, CLod0, UnpcklMask); + SDValue Unpck2 = getUnpackl(DAG, dl, MVT::v4i32, Unpck1, CLod0); SDValue XR2F = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2f64, Unpck2); SDValue CLod1 = DAG.getLoad(MVT::v2f64, dl, CLod0.getValue(1), CPIdx1, PseudoSourceValue::getConstantPool(), 0, @@ -5110,8 +4778,9 @@ SDValue Sub = DAG.getNode(ISD::FSUB, dl, MVT::v2f64, XR2F, CLod1); // Add the halves; easiest way is to swap them into another reg first. - SDValue Shuf = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v2f64, - Sub, Sub, ShufMask); + int ShufMask[2] = { 1, -1 }; + SDValue Shuf = DAG.getVectorShuffle(MVT::v2f64, dl, Sub, + DAG.getUNDEF(MVT::v2f64), ShufMask); SDValue Add = DAG.getNode(ISD::FADD, dl, MVT::v2f64, Shuf, Sub); return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Add, DAG.getIntPtrConstant(0)); @@ -7263,34 +6932,36 @@ /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values /// are assumed to be legal. bool -X86TargetLowering::isShuffleMaskLegal(SDValue Mask, MVT VT) const { +X86TargetLowering::isShuffleMaskLegal(const int *Mask, MVT VT) const { // Only do shuffles on 128-bit vector types for now. - // FIXME: pshufb, blends - if (VT.getSizeInBits() == 64) return false; - return (Mask.getNode()->getNumOperands() <= 4 || - isIdentityMask(Mask.getNode()) || - isIdentityMask(Mask.getNode(), true) || - isSplatMask(Mask.getNode()) || - X86::isPSHUFHWMask(Mask.getNode()) || - X86::isPSHUFLWMask(Mask.getNode()) || - X86::isUNPCKLMask(Mask.getNode()) || - X86::isUNPCKHMask(Mask.getNode()) || - X86::isUNPCKL_v_undef_Mask(Mask.getNode()) || - X86::isUNPCKH_v_undef_Mask(Mask.getNode())); + if (VT.getSizeInBits() == 64) + return false; + + // FIXME: pshufb, blends, palignr, shifts. + return (VT.getVectorNumElements() == 2 || + ShuffleVectorSDNode::isSplatMask(Mask, VT) || + isMOVLMask(Mask, VT) || + isSHUFPMask(Mask, VT) || + isPSHUFDMask(Mask, VT) || + isPSHUFHWMask(Mask, VT) || + isPSHUFLWMask(Mask, VT) || + isUNPCKLMask(Mask, VT) || + isUNPCKHMask(Mask, VT) || + isUNPCKL_v_undef_Mask(Mask, VT) || + isUNPCKH_v_undef_Mask(Mask, VT)); } bool -X86TargetLowering::isVectorClearMaskLegal(const std::vector &BVOps, - MVT EVT, SelectionDAG &DAG) const { - unsigned NumElts = BVOps.size(); - // Only do shuffles on 128-bit vector types for now. - if (EVT.getSizeInBits() * NumElts == 64) return false; - if (NumElts == 2) return true; - if (NumElts == 4) { - return (isMOVLMask(&BVOps[0], 4) || - isCommutedMOVL(&BVOps[0], 4, true) || - isSHUFPMask(&BVOps[0], 4) || - isCommutedSHUFP(&BVOps[0], 4)); +X86TargetLowering::isVectorClearMaskLegal(const int *Mask, MVT VT) const { + unsigned NumElts = VT.getVectorNumElements(); + // FIXME: This collection of masks seems suspect. + if (NumElts == 2) + return true; + if (NumElts == 4 && VT.getSizeInBits() == 128) { + return (isMOVLMask(Mask, VT) || + isCommutedMOVLMask(Mask, VT, true) || + isSHUFPMask(Mask, VT) || + isCommutedSHUFPMask(Mask, VT)); } return false; } @@ -8025,15 +7696,14 @@ return false; } -static bool EltsFromConsecutiveLoads(SDNode *N, SDValue PermMask, +static bool EltsFromConsecutiveLoads(SDNode *N, const int *PermMask, unsigned NumElems, MVT EVT, SDNode *&Base, SelectionDAG &DAG, MachineFrameInfo *MFI, const TargetLowering &TLI) { Base = NULL; for (unsigned i = 0; i < NumElems; ++i) { - SDValue Idx = PermMask.getOperand(i); - if (Idx.getOpcode() == ISD::UNDEF) { + if (PermMask[i] < 0) { if (!Base) return false; continue; @@ -8066,12 +7736,12 @@ /// shuffle to be an appropriate build vector so it can take advantage of // performBuildVectorCombine. static SDValue PerformShuffleCombine(SDNode *N, SelectionDAG &DAG, - const TargetLowering &TLI) { + const TargetLowering &TLI) { DebugLoc dl = N->getDebugLoc(); MVT VT = N->getValueType(0); MVT EVT = VT.getVectorElementType(); - SDValue PermMask = N->getOperand(2); - unsigned NumElems = PermMask.getNumOperands(); + const int *PermMask = cast(N)->getMask(); + unsigned NumElems = VT.getVectorNumElements(); // For x86-32 machines, if we see an insert and then a shuffle in a v2i64 // where the upper half is 0, it is advantageous to rewrite it as a build @@ -8080,9 +7750,10 @@ SDValue In[2]; In[0] = N->getOperand(0); In[1] = N->getOperand(1); - unsigned Idx0 =cast(PermMask.getOperand(0))->getZExtValue(); - unsigned Idx1 =cast(PermMask.getOperand(1))->getZExtValue(); - if (In[0].getValueType().getVectorNumElements() == NumElems && + unsigned Idx0 = PermMask[0]; + unsigned Idx1 = PermMask[1]; + // FIXME: can we take advantage of undef index? + if (PermMask[0] >= 0 && PermMask[1] >= 0 && In[Idx0/2].getOpcode() == ISD::INSERT_VECTOR_ELT && In[Idx1/2].getOpcode() == ISD::BUILD_VECTOR) { ConstantSDNode* InsertVecIdx = @@ -8546,9 +8217,9 @@ } } } else if (ShAmtOp.getOpcode() == ISD::VECTOR_SHUFFLE && - isSplatMask(ShAmtOp.getOperand(2).getNode())) { - BaseShAmt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, ShAmtOp, - DAG.getIntPtrConstant(0)); + cast(ShAmtOp)->isSplat()) { + BaseShAmt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, ShAmtOp, + DAG.getIntPtrConstant(0)); } else 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=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Thu Apr 23 22:42:54 2009 @@ -230,7 +230,8 @@ // VSHL, VSRL - Vector logical left / right shift. VSHL, VSRL, - + + // CMPPD, CMPPS - Vector double/float comparison. // CMPPD, CMPPS - Vector double/float comparison. CMPPD, CMPPS, @@ -251,80 +252,72 @@ namespace X86 { /// isPSHUFDMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to PSHUFD. - bool isPSHUFDMask(SDNode *N); + bool isPSHUFDMask(ShuffleVectorSDNode *N); /// isPSHUFHWMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to PSHUFD. - bool isPSHUFHWMask(SDNode *N); + bool isPSHUFHWMask(ShuffleVectorSDNode *N); /// isPSHUFLWMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to PSHUFD. - bool isPSHUFLWMask(SDNode *N); + bool isPSHUFLWMask(ShuffleVectorSDNode *N); /// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to SHUFP*. - bool isSHUFPMask(SDNode *N); + bool isSHUFPMask(ShuffleVectorSDNode *N); /// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVHLPS. - bool isMOVHLPSMask(SDNode *N); + bool isMOVHLPSMask(ShuffleVectorSDNode *N); /// isMOVHLPS_v_undef_Mask - Special case of isMOVHLPSMask for canonical form /// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef, /// <2, 3, 2, 3> - bool isMOVHLPS_v_undef_Mask(SDNode *N); + bool isMOVHLPS_v_undef_Mask(ShuffleVectorSDNode *N); /// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand - /// specifies a shuffle of elements that is suitable for input to MOVLP{S|D}. - bool isMOVLPMask(SDNode *N); + /// specifies a shuffle of elements that is suitable for MOVLP{S|D}. + bool isMOVLPMask(ShuffleVectorSDNode *N); /// isMOVHPMask - Return true if the specified VECTOR_SHUFFLE operand - /// specifies a shuffle of elements that is suitable for input to MOVHP{S|D} + /// specifies a shuffle of elements that is suitable for MOVHP{S|D}. /// as well as MOVLHPS. - bool isMOVHPMask(SDNode *N); + bool isMOVHPMask(ShuffleVectorSDNode *N); /// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKL. - bool isUNPCKLMask(SDNode *N, bool V2IsSplat = false); + bool isUNPCKLMask(ShuffleVectorSDNode *N, bool V2IsSplat = false); /// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKH. - bool isUNPCKHMask(SDNode *N, bool V2IsSplat = false); + bool isUNPCKHMask(ShuffleVectorSDNode *N, bool V2IsSplat = false); /// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form /// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef, /// <0, 0, 1, 1> - bool isUNPCKL_v_undef_Mask(SDNode *N); + bool isUNPCKL_v_undef_Mask(ShuffleVectorSDNode *N); /// isUNPCKH_v_undef_Mask - Special case of isUNPCKHMask for canonical form /// of vector_shuffle v, v, <2, 6, 3, 7>, i.e. vector_shuffle v, undef, /// <2, 2, 3, 3> - bool isUNPCKH_v_undef_Mask(SDNode *N); + bool isUNPCKH_v_undef_Mask(ShuffleVectorSDNode *N); /// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSS, /// MOVSD, and MOVD, i.e. setting the lowest element. - bool isMOVLMask(SDNode *N); + bool isMOVLMask(ShuffleVectorSDNode *N); /// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSHDUP. - bool isMOVSHDUPMask(SDNode *N); + bool isMOVSHDUPMask(ShuffleVectorSDNode *N); /// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSLDUP. - bool isMOVSLDUPMask(SDNode *N); - - /// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand - /// specifies a splat of a single element. - bool isSplatMask(SDNode *N); - - /// isSplatLoMask - Return true if the specified VECTOR_SHUFFLE operand - /// specifies a splat of zero element. - bool isSplatLoMask(SDNode *N); + bool isMOVSLDUPMask(ShuffleVectorSDNode *N); /// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVDDUP. - bool isMOVDDUPMask(SDNode *N); + bool isMOVDDUPMask(ShuffleVectorSDNode *N); /// getShuffleSHUFImmediate - Return the appropriate immediate to shuffle /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUF* and SHUFP* @@ -477,14 +470,13 @@ /// support *some* VECTOR_SHUFFLE operations, those with specific masks. /// By default, if a target supports the VECTOR_SHUFFLE node, all mask /// values are assumed to be legal. - virtual bool isShuffleMaskLegal(SDValue Mask, MVT VT) const; + virtual bool isShuffleMaskLegal(const int *Mask, MVT VT) const; /// isVectorClearMaskLegal - Similar to isShuffleMaskLegal. This is /// used by Targets can use this to indicate if there is a suitable /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant /// pool entry. - virtual bool isVectorClearMaskLegal(const std::vector &BVOps, - MVT EVT, SelectionDAG &DAG) const; + virtual bool isVectorClearMaskLegal(const int *Mask, MVT VT) const; /// ShouldShrinkFPConstant - If true, then instruction selection should /// seek to shrink the FP constant of the specified type to a smaller type Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Thu Apr 23 22:42:54 2009 @@ -3801,6 +3801,7 @@ (implicit EFLAGS)), (DEC32m addr:$dst)>, Requires<[In32BitMode]>; + //===----------------------------------------------------------------------===// // Floating Point Stack Support //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/Target/X86/X86InstrMMX.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrMMX.td?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrMMX.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrMMX.td Thu Apr 23 22:42:54 2009 @@ -30,33 +30,37 @@ // MMX_SHUFFLE_get_shuf_imm xform function: convert vector_shuffle mask to // PSHUFW imm. -def MMX_SHUFFLE_get_shuf_imm : SDNodeXForm; // Patterns for: vector_shuffle v1, v2, <2, 6, 3, 7, ...> -def MMX_UNPCKH_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isUNPCKHMask(N); +def mmx_unpckh : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKHMask(cast(N)); }]>; // Patterns for: vector_shuffle v1, v2, <0, 4, 2, 5, ...> -def MMX_UNPCKL_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isUNPCKLMask(N); +def mmx_unpckl : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKLMask(cast(N)); }]>; // Patterns for: vector_shuffle v1, , <0, 0, 1, 1, ...> -def MMX_UNPCKH_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isUNPCKH_v_undef_Mask(N); +def mmx_unpckh_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKH_v_undef_Mask(cast(N)); }]>; // Patterns for: vector_shuffle v1, , <2, 2, 3, 3, ...> -def MMX_UNPCKL_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isUNPCKL_v_undef_Mask(N); +def mmx_unpckl_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKL_v_undef_Mask(cast(N)); }]>; -// Patterns for shuffling. -def MMX_PSHUFW_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isPSHUFDMask(N); +def mmx_pshufw : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isPSHUFDMask(cast(N)); }], MMX_SHUFFLE_get_shuf_imm>; //===----------------------------------------------------------------------===// @@ -185,9 +189,8 @@ def MMX_MOVQ2DQrr : SSDIi8<0xD6, MRMDestMem, (outs VR128:$dst), (ins VR64:$src), "movq2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, - (v2i64 (vector_shuffle immAllZerosV, - (v2i64 (scalar_to_vector (i64 (bitconvert VR64:$src)))), - MOVL_shuffle_mask)))]>; + (movl immAllZerosV, + (v2i64 (scalar_to_vector (i64 (bitconvert VR64:$src))))))]>; let neverHasSideEffects = 1 in def MMX_MOVQ2FR64rr: SSDIi8<0xD6, MRMDestMem, (outs FR64:$dst), (ins VR64:$src), @@ -319,86 +322,74 @@ (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpckhbw\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v8i8 (vector_shuffle VR64:$src1, VR64:$src2, - MMX_UNPCKH_shuffle_mask)))]>; + (v8i8 (mmx_unpckh VR64:$src1, VR64:$src2)))]>; def MMX_PUNPCKHBWrm : MMXI<0x68, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpckhbw\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v8i8 (vector_shuffle VR64:$src1, - (bc_v8i8 (load_mmx addr:$src2)), - MMX_UNPCKH_shuffle_mask)))]>; + (v8i8 (mmx_unpckh VR64:$src1, + (bc_v8i8 (load_mmx addr:$src2)))))]>; def MMX_PUNPCKHWDrr : MMXI<0x69, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpckhwd\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v4i16 (vector_shuffle VR64:$src1, VR64:$src2, - MMX_UNPCKH_shuffle_mask)))]>; + (v4i16 (mmx_unpckh VR64:$src1, VR64:$src2)))]>; def MMX_PUNPCKHWDrm : MMXI<0x69, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpckhwd\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v4i16 (vector_shuffle VR64:$src1, - (bc_v4i16 (load_mmx addr:$src2)), - MMX_UNPCKH_shuffle_mask)))]>; + (v4i16 (mmx_unpckh VR64:$src1, + (bc_v4i16 (load_mmx addr:$src2)))))]>; def MMX_PUNPCKHDQrr : MMXI<0x6A, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpckhdq\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v2i32 (vector_shuffle VR64:$src1, VR64:$src2, - MMX_UNPCKH_shuffle_mask)))]>; + (v2i32 (mmx_unpckh VR64:$src1, VR64:$src2)))]>; def MMX_PUNPCKHDQrm : MMXI<0x6A, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpckhdq\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v2i32 (vector_shuffle VR64:$src1, - (bc_v2i32 (load_mmx addr:$src2)), - MMX_UNPCKH_shuffle_mask)))]>; + (v2i32 (mmx_unpckh VR64:$src1, + (bc_v2i32 (load_mmx addr:$src2)))))]>; // Unpack Low Packed Data Instructions def MMX_PUNPCKLBWrr : MMXI<0x60, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpcklbw\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v8i8 (vector_shuffle VR64:$src1, VR64:$src2, - MMX_UNPCKL_shuffle_mask)))]>; + (v8i8 (mmx_unpckl VR64:$src1, VR64:$src2)))]>; def MMX_PUNPCKLBWrm : MMXI<0x60, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpcklbw\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v8i8 (vector_shuffle VR64:$src1, - (bc_v8i8 (load_mmx addr:$src2)), - MMX_UNPCKL_shuffle_mask)))]>; + (v8i8 (mmx_unpckl VR64:$src1, + (bc_v8i8 (load_mmx addr:$src2)))))]>; def MMX_PUNPCKLWDrr : MMXI<0x61, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpcklwd\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v4i16 (vector_shuffle VR64:$src1, VR64:$src2, - MMX_UNPCKL_shuffle_mask)))]>; + (v4i16 (mmx_unpckl VR64:$src1, VR64:$src2)))]>; def MMX_PUNPCKLWDrm : MMXI<0x61, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpcklwd\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v4i16 (vector_shuffle VR64:$src1, - (bc_v4i16 (load_mmx addr:$src2)), - MMX_UNPCKL_shuffle_mask)))]>; + (v4i16 (mmx_unpckl VR64:$src1, + (bc_v4i16 (load_mmx addr:$src2)))))]>; def MMX_PUNPCKLDQrr : MMXI<0x62, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpckldq\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v2i32 (vector_shuffle VR64:$src1, VR64:$src2, - MMX_UNPCKL_shuffle_mask)))]>; + (v2i32 (mmx_unpckl VR64:$src1, VR64:$src2)))]>; def MMX_PUNPCKLDQrm : MMXI<0x62, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpckldq\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v2i32 (vector_shuffle VR64:$src1, - (bc_v2i32 (load_mmx addr:$src2)), - MMX_UNPCKL_shuffle_mask)))]>; + (v2i32 (mmx_unpckl VR64:$src1, + (bc_v2i32 (load_mmx addr:$src2)))))]>; } // -- Pack Instructions @@ -411,17 +402,13 @@ (outs VR64:$dst), (ins VR64:$src1, i8imm:$src2), "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", [(set VR64:$dst, - (v4i16 (vector_shuffle - VR64:$src1, (undef), - MMX_PSHUFW_shuffle_mask:$src2)))]>; + (v4i16 (mmx_pshufw:$src2 VR64:$src1, (undef))))]>; def MMX_PSHUFWmi : MMXIi8<0x70, MRMSrcMem, (outs VR64:$dst), (ins i64mem:$src1, i8imm:$src2), "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", [(set VR64:$dst, - (v4i16 (vector_shuffle - (bc_v4i16 (load_mmx addr:$src1)), - (undef), - MMX_PSHUFW_shuffle_mask:$src2)))]>; + (mmx_pshufw:$src2 (bc_v4i16 (load_mmx addr:$src1)), + (undef)))]>; // -- Conversion Instructions let neverHasSideEffects = 1 in { @@ -627,34 +614,27 @@ // Patterns to perform canonical versions of vector shuffling. let AddedComplexity = 10 in { - def : Pat<(v8i8 (vector_shuffle VR64:$src, (undef), - MMX_UNPCKL_v_undef_shuffle_mask)), + def : Pat<(v8i8 (mmx_unpckl_undef VR64:$src, (undef))), (MMX_PUNPCKLBWrr VR64:$src, VR64:$src)>; - def : Pat<(v4i16 (vector_shuffle VR64:$src, (undef), - MMX_UNPCKL_v_undef_shuffle_mask)), + def : Pat<(v4i16 (mmx_unpckl_undef VR64:$src, (undef))), (MMX_PUNPCKLWDrr VR64:$src, VR64:$src)>; - def : Pat<(v2i32 (vector_shuffle VR64:$src, (undef), - MMX_UNPCKL_v_undef_shuffle_mask)), + def : Pat<(v2i32 (mmx_unpckl_undef VR64:$src, (undef))), (MMX_PUNPCKLDQrr VR64:$src, VR64:$src)>; } let AddedComplexity = 10 in { - def : Pat<(v8i8 (vector_shuffle VR64:$src, (undef), - MMX_UNPCKH_v_undef_shuffle_mask)), + def : Pat<(v8i8 (mmx_unpckh_undef VR64:$src, (undef))), (MMX_PUNPCKHBWrr VR64:$src, VR64:$src)>; - def : Pat<(v4i16 (vector_shuffle VR64:$src, (undef), - MMX_UNPCKH_v_undef_shuffle_mask)), + def : Pat<(v4i16 (mmx_unpckh_undef VR64:$src, (undef))), (MMX_PUNPCKHWDrr VR64:$src, VR64:$src)>; - def : Pat<(v2i32 (vector_shuffle VR64:$src, (undef), - MMX_UNPCKH_v_undef_shuffle_mask)), + def : Pat<(v2i32 (mmx_unpckh_undef VR64:$src, (undef))), (MMX_PUNPCKHDQrr VR64:$src, VR64:$src)>; } // Patterns to perform vector shuffling with a zeroed out vector. let AddedComplexity = 20 in { - def : Pat<(bc_v2i32 (vector_shuffle immAllZerosV, - (v2i32 (scalar_to_vector (load_mmx addr:$src))), - MMX_UNPCKL_shuffle_mask)), + def : Pat<(bc_v2i32 (mmx_unpckl immAllZerosV, + (v2i32 (scalar_to_vector (load_mmx addr:$src))))), (MMX_PUNPCKLDQrm VR64:$src, VR64:$src)>; } Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Thu Apr 23 22:42:54 2009 @@ -175,102 +175,107 @@ // SHUFFLE_get_shuf_imm xform function: convert vector_shuffle mask to PSHUF*, // SHUFP* etc. imm. -def SHUFFLE_get_shuf_imm : SDNodeXForm; // SHUFFLE_get_pshufhw_imm xform function: convert vector_shuffle mask to // PSHUFHW imm. -def SHUFFLE_get_pshufhw_imm : SDNodeXForm; // SHUFFLE_get_pshuflw_imm xform function: convert vector_shuffle mask to // PSHUFLW imm. -def SHUFFLE_get_pshuflw_imm : SDNodeXForm; -def SSE_splat_mask : PatLeaf<(build_vector), [{ - return X86::isSplatMask(N); -}], SHUFFLE_get_shuf_imm>; - -def SSE_splat_lo_mask : PatLeaf<(build_vector), [{ - return X86::isSplatLoMask(N); +def splat_lo : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + ShuffleVectorSDNode *SVOp = cast(N); + return SVOp->isSplat() && SVOp->getSplatIndex() == 0; }]>; -def MOVDDUP_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isMOVDDUPMask(N); +def movddup : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVDDUPMask(cast(N)); }]>; -def MOVHLPS_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isMOVHLPSMask(N); +def movhlps : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVHLPSMask(cast(N)); }]>; -def MOVHLPS_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isMOVHLPS_v_undef_Mask(N); +def movhlps_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVHLPS_v_undef_Mask(cast(N)); }]>; -def MOVHP_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isMOVHPMask(N); +def movhp : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVHPMask(cast(N)); }]>; -def MOVLP_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isMOVLPMask(N); +def movlp : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVLPMask(cast(N)); }]>; -def MOVL_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isMOVLMask(N); +def movl : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVLMask(cast(N)); }]>; -def MOVSHDUP_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isMOVSHDUPMask(N); +def movshdup : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVSHDUPMask(cast(N)); }]>; -def MOVSLDUP_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isMOVSLDUPMask(N); +def movsldup : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVSLDUPMask(cast(N)); }]>; -def UNPCKL_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isUNPCKLMask(N); +def unpckl : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKLMask(cast(N)); }]>; -def UNPCKH_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isUNPCKHMask(N); +def unpckh : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKHMask(cast(N)); }]>; -def UNPCKL_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isUNPCKL_v_undef_Mask(N); +def unpckl_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKL_v_undef_Mask(cast(N)); }]>; -def UNPCKH_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isUNPCKH_v_undef_Mask(N); +def unpckh_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKH_v_undef_Mask(cast(N)); }]>; -def PSHUFD_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isPSHUFDMask(N); -}], SHUFFLE_get_shuf_imm>; - -def PSHUFHW_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isPSHUFHWMask(N); -}], SHUFFLE_get_pshufhw_imm>; - -def PSHUFLW_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isPSHUFLWMask(N); -}], SHUFFLE_get_pshuflw_imm>; - -def SHUFP_unary_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isPSHUFDMask(N); +def pshufd : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isPSHUFDMask(cast(N)); }], SHUFFLE_get_shuf_imm>; -def SHUFP_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isSHUFPMask(N); +def shufp : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isSHUFPMask(cast(N)); }], SHUFFLE_get_shuf_imm>; -def PSHUFD_binary_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isSHUFPMask(N); -}], SHUFFLE_get_shuf_imm>; +def pshufhw : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isPSHUFHWMask(cast(N)); +}], SHUFFLE_get_pshufhw_imm>; +def pshuflw : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isPSHUFLWMask(cast(N)); +}], SHUFFLE_get_pshuflw_imm>; //===----------------------------------------------------------------------===// // SSE scalar FP Instructions @@ -704,16 +709,14 @@ (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), "movlps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (vector_shuffle VR128:$src1, - (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2)))), - MOVLP_shuffle_mask)))]>; + (movlp VR128:$src1, + (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))))]>; def MOVHPSrm : PSI<0x16, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), "movhps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (vector_shuffle VR128:$src1, - (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2)))), - MOVHP_shuffle_mask)))]>; + (movhp VR128:$src1, + (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" @@ -728,29 +731,25 @@ def MOVHPSmr : PSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movhps\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract - (v2f64 (vector_shuffle - (bc_v2f64 (v4f32 VR128:$src)), (undef), - UNPCKH_shuffle_mask)), (iPTR 0))), - addr:$dst)]>; + (unpckh (bc_v2f64 (v4f32 VR128:$src)), + (undef)), (iPTR 0))), addr:$dst)]>; let Constraints = "$src1 = $dst" in { let AddedComplexity = 20 in { def MOVLHPSrr : PSI<0x16, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "movlhps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (vector_shuffle VR128:$src1, VR128:$src2, - MOVHP_shuffle_mask)))]>; + (v4f32 (movhp VR128:$src1, VR128:$src2)))]>; def MOVHLPSrr : PSI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "movhlps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (vector_shuffle VR128:$src1, VR128:$src2, - MOVHLPS_shuffle_mask)))]>; + (v4f32 (movhlps VR128:$src1, VR128:$src2)))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" let AddedComplexity = 20 in -def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), MOVDDUP_shuffle_mask)), +def : Pat<(v4f32 (movddup VR128:$src, (undef))), (MOVLHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; @@ -908,51 +907,41 @@ let isConvertibleToThreeAddress = 1 in // Convert to pshufd def SHUFPSrri : PSIi8<0xC6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, - VR128:$src2, i32i8imm:$src3), + VR128:$src2, i8imm:$src3), "shufps\t{$src3, $src2, $dst|$dst, $src2, $src3}", [(set VR128:$dst, - (v4f32 (vector_shuffle - VR128:$src1, VR128:$src2, - SHUFP_shuffle_mask:$src3)))]>; + (v4f32 (shufp:$src3 VR128:$src1, VR128:$src2)))]>; def SHUFPSrmi : PSIi8<0xC6, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, - f128mem:$src2, i32i8imm:$src3), + f128mem:$src2, i8imm:$src3), "shufps\t{$src3, $src2, $dst|$dst, $src2, $src3}", [(set VR128:$dst, - (v4f32 (vector_shuffle - VR128:$src1, (memopv4f32 addr:$src2), - SHUFP_shuffle_mask:$src3)))]>; + (v4f32 (shufp:$src3 + VR128:$src1, (memopv4f32 addr:$src2))))]>; let AddedComplexity = 10 in { def UNPCKHPSrr : PSI<0x15, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "unpckhps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (vector_shuffle - VR128:$src1, VR128:$src2, - UNPCKH_shuffle_mask)))]>; + (v4f32 (unpckh VR128:$src1, VR128:$src2)))]>; def UNPCKHPSrm : PSI<0x15, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), "unpckhps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (vector_shuffle - VR128:$src1, (memopv4f32 addr:$src2), - UNPCKH_shuffle_mask)))]>; + (v4f32 (unpckh VR128:$src1, + (memopv4f32 addr:$src2))))]>; def UNPCKLPSrr : PSI<0x14, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "unpcklps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (vector_shuffle - VR128:$src1, VR128:$src2, - UNPCKL_shuffle_mask)))]>; + (v4f32 (unpckl VR128:$src1, VR128:$src2)))]>; def UNPCKLPSrm : PSI<0x14, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), "unpcklps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (vector_shuffle - VR128:$src1, (memopv4f32 addr:$src2), - UNPCKL_shuffle_mask)))]>; + (unpckl VR128:$src1, (memopv4f32 addr:$src2)))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" @@ -1044,8 +1033,7 @@ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "movss\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (vector_shuffle VR128:$src1, VR128:$src2, - MOVL_shuffle_mask)))]>; + (v4f32 (movl VR128:$src1, VR128:$src2)))]>; } // Move to lower bits of a VR128 and zeroing upper bits. @@ -1451,16 +1439,14 @@ (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), "movlpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (vector_shuffle VR128:$src1, - (scalar_to_vector (loadf64 addr:$src2)), - MOVLP_shuffle_mask)))]>; + (v2f64 (movlp VR128:$src1, + (scalar_to_vector (loadf64 addr:$src2)))))]>; def MOVHPDrm : PDI<0x16, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), "movhpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (vector_shuffle VR128:$src1, - (scalar_to_vector (loadf64 addr:$src2)), - MOVHP_shuffle_mask)))]>; + (v2f64 (movhp VR128:$src1, + (scalar_to_vector (loadf64 addr:$src2)))))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" @@ -1474,9 +1460,8 @@ def MOVHPDmr : PDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movhpd\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract - (v2f64 (vector_shuffle VR128:$src, (undef), - UNPCKH_shuffle_mask)), (iPTR 0))), - addr:$dst)]>; + (v2f64 (unpckh VR128:$src, (undef))), + (iPTR 0))), addr:$dst)]>; // SSE2 instructions without OpSize prefix def Int_CVTDQ2PSrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), @@ -1744,48 +1729,39 @@ def SHUFPDrri : PDIi8<0xC6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2, i8imm:$src3), "shufpd\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, (v2f64 (vector_shuffle - VR128:$src1, VR128:$src2, - SHUFP_shuffle_mask:$src3)))]>; + [(set VR128:$dst, + (v2f64 (shufp:$src3 VR128:$src1, VR128:$src2)))]>; def SHUFPDrmi : PDIi8<0xC6, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2, i8imm:$src3), "shufpd\t{$src3, $src2, $dst|$dst, $src2, $src3}", [(set VR128:$dst, - (v2f64 (vector_shuffle - VR128:$src1, (memopv2f64 addr:$src2), - SHUFP_shuffle_mask:$src3)))]>; + (v2f64 (shufp:$src3 + VR128:$src1, (memopv2f64 addr:$src2))))]>; let AddedComplexity = 10 in { def UNPCKHPDrr : PDI<0x15, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "unpckhpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (vector_shuffle - VR128:$src1, VR128:$src2, - UNPCKH_shuffle_mask)))]>; + (v2f64 (unpckh VR128:$src1, VR128:$src2)))]>; def UNPCKHPDrm : PDI<0x15, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), "unpckhpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (vector_shuffle - VR128:$src1, (memopv2f64 addr:$src2), - UNPCKH_shuffle_mask)))]>; + (v2f64 (unpckh VR128:$src1, + (memopv2f64 addr:$src2))))]>; def UNPCKLPDrr : PDI<0x14, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "unpcklpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (vector_shuffle - VR128:$src1, VR128:$src2, - UNPCKL_shuffle_mask)))]>; + (v2f64 (unpckl VR128:$src1, VR128:$src2)))]>; def UNPCKLPDrm : PDI<0x14, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), "unpcklpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (vector_shuffle - VR128:$src1, (memopv2f64 addr:$src2), - UNPCKL_shuffle_mask)))]>; + (unpckl VR128:$src1, (memopv2f64 addr:$src2)))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" @@ -2043,49 +2019,43 @@ def PSHUFDri : PDIi8<0x70, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), "pshufd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v4i32 (vector_shuffle - VR128:$src1, (undef), - PSHUFD_shuffle_mask:$src2)))]>; + [(set VR128:$dst, (v4i32 (pshufd:$src2 + VR128:$src1, (undef))))]>; def PSHUFDmi : PDIi8<0x70, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src1, i8imm:$src2), "pshufd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v4i32 (vector_shuffle + [(set VR128:$dst, (v4i32 (pshufd:$src2 (bc_v4i32(memopv2i64 addr:$src1)), - (undef), - PSHUFD_shuffle_mask:$src2)))]>; + (undef))))]>; // SSE2 with ImmT == Imm8 and XS prefix. def PSHUFHWri : Ii8<0x70, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), "pshufhw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v8i16 (vector_shuffle - VR128:$src1, (undef), - PSHUFHW_shuffle_mask:$src2)))]>, + [(set VR128:$dst, (v8i16 (pshufhw:$src2 VR128:$src1, + (undef))))]>, XS, Requires<[HasSSE2]>; def PSHUFHWmi : Ii8<0x70, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src1, i8imm:$src2), "pshufhw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v8i16 (vector_shuffle - (bc_v8i16 (memopv2i64 addr:$src1)), - (undef), - PSHUFHW_shuffle_mask:$src2)))]>, + [(set VR128:$dst, (v8i16 (pshufhw:$src2 + (bc_v8i16 (memopv2i64 addr:$src1)), + (undef))))]>, XS, Requires<[HasSSE2]>; // SSE2 with ImmT == Imm8 and XD prefix. def PSHUFLWri : Ii8<0x70, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, i32i8imm:$src2), + (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), "pshuflw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v8i16 (vector_shuffle - VR128:$src1, (undef), - PSHUFLW_shuffle_mask:$src2)))]>, + [(set VR128:$dst, (v8i16 (pshuflw:$src2 VR128:$src1, + (undef))))]>, XD, Requires<[HasSSE2]>; def PSHUFLWmi : Ii8<0x70, MRMSrcMem, - (outs VR128:$dst), (ins i128mem:$src1, i32i8imm:$src2), + (outs VR128:$dst), (ins i128mem:$src1, i8imm:$src2), "pshuflw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v8i16 (vector_shuffle - (bc_v8i16 (memopv2i64 addr:$src1)), - (undef), - PSHUFLW_shuffle_mask:$src2)))]>, + [(set VR128:$dst, (v8i16 (pshuflw:$src2 + (bc_v8i16 (memopv2i64 addr:$src1)), + (undef))))]>, XD, Requires<[HasSSE2]>; @@ -2094,107 +2064,91 @@ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpcklbw\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v16i8 (vector_shuffle VR128:$src1, VR128:$src2, - UNPCKL_shuffle_mask)))]>; + (v16i8 (unpckl VR128:$src1, VR128:$src2)))]>; def PUNPCKLBWrm : PDI<0x60, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpcklbw\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v16i8 (vector_shuffle VR128:$src1, - (bc_v16i8 (memopv2i64 addr:$src2)), - UNPCKL_shuffle_mask)))]>; + (unpckl VR128:$src1, + (bc_v16i8 (memopv2i64 addr:$src2))))]>; def PUNPCKLWDrr : PDI<0x61, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpcklwd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v8i16 (vector_shuffle VR128:$src1, VR128:$src2, - UNPCKL_shuffle_mask)))]>; + (v8i16 (unpckl VR128:$src1, VR128:$src2)))]>; def PUNPCKLWDrm : PDI<0x61, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpcklwd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v8i16 (vector_shuffle VR128:$src1, - (bc_v8i16 (memopv2i64 addr:$src2)), - UNPCKL_shuffle_mask)))]>; + (unpckl VR128:$src1, + (bc_v8i16 (memopv2i64 addr:$src2))))]>; def PUNPCKLDQrr : PDI<0x62, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckldq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4i32 (vector_shuffle VR128:$src1, VR128:$src2, - UNPCKL_shuffle_mask)))]>; + (v4i32 (unpckl VR128:$src1, VR128:$src2)))]>; def PUNPCKLDQrm : PDI<0x62, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckldq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4i32 (vector_shuffle VR128:$src1, - (bc_v4i32 (memopv2i64 addr:$src2)), - UNPCKL_shuffle_mask)))]>; + (unpckl VR128:$src1, + (bc_v4i32 (memopv2i64 addr:$src2))))]>; def PUNPCKLQDQrr : PDI<0x6C, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpcklqdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2i64 (vector_shuffle VR128:$src1, VR128:$src2, - UNPCKL_shuffle_mask)))]>; + (v2i64 (unpckl VR128:$src1, VR128:$src2)))]>; def PUNPCKLQDQrm : PDI<0x6C, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpcklqdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2i64 (vector_shuffle VR128:$src1, - (memopv2i64 addr:$src2), - UNPCKL_shuffle_mask)))]>; + (v2i64 (unpckl VR128:$src1, + (memopv2i64 addr:$src2))))]>; def PUNPCKHBWrr : PDI<0x68, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckhbw\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v16i8 (vector_shuffle VR128:$src1, VR128:$src2, - UNPCKH_shuffle_mask)))]>; + (v16i8 (unpckh VR128:$src1, VR128:$src2)))]>; def PUNPCKHBWrm : PDI<0x68, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckhbw\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (v16i8 (vector_shuffle VR128:$src1, - (bc_v16i8 (memopv2i64 addr:$src2)), - UNPCKH_shuffle_mask)))]>; + [(set VR128:$dst, + (unpckh VR128:$src1, + (bc_v16i8 (memopv2i64 addr:$src2))))]>; def PUNPCKHWDrr : PDI<0x69, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckhwd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v8i16 (vector_shuffle VR128:$src1, VR128:$src2, - UNPCKH_shuffle_mask)))]>; + (v8i16 (unpckh VR128:$src1, VR128:$src2)))]>; def PUNPCKHWDrm : PDI<0x69, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckhwd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v8i16 (vector_shuffle VR128:$src1, - (bc_v8i16 (memopv2i64 addr:$src2)), - UNPCKH_shuffle_mask)))]>; + (unpckh VR128:$src1, + (bc_v8i16 (memopv2i64 addr:$src2))))]>; def PUNPCKHDQrr : PDI<0x6A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckhdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4i32 (vector_shuffle VR128:$src1, VR128:$src2, - UNPCKH_shuffle_mask)))]>; + (v4i32 (unpckh VR128:$src1, VR128:$src2)))]>; def PUNPCKHDQrm : PDI<0x6A, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckhdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4i32 (vector_shuffle VR128:$src1, - (bc_v4i32 (memopv2i64 addr:$src2)), - UNPCKH_shuffle_mask)))]>; + (unpckh VR128:$src1, + (bc_v4i32 (memopv2i64 addr:$src2))))]>; def PUNPCKHQDQrr : PDI<0x6D, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckhqdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2i64 (vector_shuffle VR128:$src1, VR128:$src2, - UNPCKH_shuffle_mask)))]>; + (v2i64 (unpckh VR128:$src1, VR128:$src2)))]>; def PUNPCKHQDQrm : PDI<0x6D, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckhqdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2i64 (vector_shuffle VR128:$src1, - (memopv2i64 addr:$src2), - UNPCKH_shuffle_mask)))]>; + (v2i64 (unpckh VR128:$src1, + (memopv2i64 addr:$src2))))]>; } // Extract / Insert @@ -2357,8 +2311,7 @@ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "movsd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (vector_shuffle VR128:$src1, VR128:$src2, - MOVL_shuffle_mask)))]>; + (v2f64 (movl VR128:$src1, VR128:$src2)))]>; } // Store / copy lower 64-bits of a XMM register. @@ -2449,44 +2402,35 @@ // Move Instructions def MOVSHDUPrr : S3SI<0x16, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movshdup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4f32 (vector_shuffle - VR128:$src, (undef), - MOVSHDUP_shuffle_mask)))]>; + [(set VR128:$dst, (v4f32 (movshdup + VR128:$src, (undef))))]>; def MOVSHDUPrm : S3SI<0x16, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movshdup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4f32 (vector_shuffle - (memopv4f32 addr:$src), (undef), - MOVSHDUP_shuffle_mask)))]>; + [(set VR128:$dst, (movshdup + (memopv4f32 addr:$src), (undef)))]>; def MOVSLDUPrr : S3SI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movsldup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4f32 (vector_shuffle - VR128:$src, (undef), - MOVSLDUP_shuffle_mask)))]>; + [(set VR128:$dst, (v4f32 (movsldup + VR128:$src, (undef))))]>; def MOVSLDUPrm : S3SI<0x12, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movsldup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4f32 (vector_shuffle - (memopv4f32 addr:$src), (undef), - MOVSLDUP_shuffle_mask)))]>; + [(set VR128:$dst, (movsldup + (memopv4f32 addr:$src), (undef)))]>; def MOVDDUPrr : S3DI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movddup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (vector_shuffle VR128:$src, (undef), - MOVDDUP_shuffle_mask)))]>; + [(set VR128:$dst,(v2f64 (movddup VR128:$src, (undef))))]>; def MOVDDUPrm : S3DI<0x12, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), "movddup\t{$src, $dst|$dst, $src}", [(set VR128:$dst, - (v2f64 (vector_shuffle - (scalar_to_vector (loadf64 addr:$src)), - (undef), MOVDDUP_shuffle_mask)))]>; - -def : Pat<(vector_shuffle - (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src)))), - (undef), MOVDDUP_shuffle_mask), + (v2f64 (movddup (scalar_to_vector (loadf64 addr:$src)), + (undef))))]>; + +def : Pat<(movddup (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src)))), + (undef)), (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>; -def : Pat<(vector_shuffle - (memopv2f64 addr:$src), (undef), MOVDDUP_shuffle_mask), +def : Pat<(movddup (memopv2f64 addr:$src), (undef)), (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>; @@ -2555,22 +2499,18 @@ // vector_shuffle v1, <1, 1, 3, 3> let AddedComplexity = 15 in -def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), - MOVSHDUP_shuffle_mask)), +def : Pat<(v4i32 (movshdup VR128:$src, (undef))), (MOVSHDUPrr VR128:$src)>, Requires<[HasSSE3]>; let AddedComplexity = 20 in -def : Pat<(v4i32 (vector_shuffle (bc_v4i32 (memopv2i64 addr:$src)), (undef), - MOVSHDUP_shuffle_mask)), +def : Pat<(v4i32 (movshdup (bc_v4i32 (memopv2i64 addr:$src)), (undef))), (MOVSHDUPrm addr:$src)>, Requires<[HasSSE3]>; // vector_shuffle v1, <0, 0, 2, 2> let AddedComplexity = 15 in - def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), - MOVSLDUP_shuffle_mask)), + def : Pat<(v4i32 (movsldup VR128:$src, (undef))), (MOVSLDUPrr VR128:$src)>, Requires<[HasSSE3]>; let AddedComplexity = 20 in - def : Pat<(v4i32 (vector_shuffle (bc_v4i32 (memopv2i64 addr:$src)), (undef), - MOVSLDUP_shuffle_mask)), + def : Pat<(v4i32 (movsldup (bc_v4i32 (memopv2i64 addr:$src)), (undef))), (MOVSLDUPrm addr:$src)>, Requires<[HasSSE3]>; //===----------------------------------------------------------------------===// @@ -2911,207 +2851,173 @@ // Splat v2f64 / v2i64 let AddedComplexity = 10 in { -def : Pat<(vector_shuffle (v2f64 VR128:$src), (undef), SSE_splat_lo_mask:$sm), +def : Pat<(splat_lo (v2f64 VR128:$src), (undef)), (UNPCKLPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(vector_shuffle (v2f64 VR128:$src), (undef), UNPCKH_shuffle_mask:$sm), +def : Pat<(unpckh (v2f64 VR128:$src), (undef)), (UNPCKHPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(vector_shuffle (v2i64 VR128:$src), (undef), SSE_splat_lo_mask:$sm), +def : Pat<(splat_lo (v2i64 VR128:$src), (undef)), (PUNPCKLQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(vector_shuffle (v2i64 VR128:$src), (undef), UNPCKH_shuffle_mask:$sm), +def : Pat<(unpckh (v2i64 VR128:$src), (undef)), (PUNPCKHQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; } // Special unary SHUFPSrri case. -def : Pat<(v4f32 (vector_shuffle VR128:$src1, (undef), - SHUFP_unary_shuffle_mask:$sm)), - (SHUFPSrri VR128:$src1, VR128:$src1, SHUFP_unary_shuffle_mask:$sm)>, +def : Pat<(v4f32 (pshufd:$src3 VR128:$src1, (undef))), + (SHUFPSrri VR128:$src1, VR128:$src1, + (SHUFFLE_get_shuf_imm VR128:$src3))>, Requires<[HasSSE1]>; +let AddedComplexity = 5 in +def : Pat<(v4f32 (pshufd:$src2 VR128:$src1, (undef))), + (PSHUFDri VR128:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>, + Requires<[HasSSE2]>; +// Special unary SHUFPDrri case. +def : Pat<(v2i64 (pshufd:$src3 VR128:$src1, (undef))), + (SHUFPDrri VR128:$src1, VR128:$src1, + (SHUFFLE_get_shuf_imm VR128:$src3))>, + Requires<[HasSSE2]>; // Special unary SHUFPDrri case. -def : Pat<(v2f64 (vector_shuffle VR128:$src1, (undef), - SHUFP_unary_shuffle_mask:$sm)), - (SHUFPDrri VR128:$src1, VR128:$src1, SHUFP_unary_shuffle_mask:$sm)>, +def : Pat<(v2f64 (pshufd:$src3 VR128:$src1, (undef))), + (SHUFPDrri VR128:$src1, VR128:$src1, + (SHUFFLE_get_shuf_imm VR128:$src3))>, Requires<[HasSSE2]>; // Unary v4f32 shuffle with PSHUF* in order to fold a load. -def : Pat<(vector_shuffle (bc_v4i32 (memopv4f32 addr:$src1)), (undef), - SHUFP_unary_shuffle_mask:$sm), - (PSHUFDmi addr:$src1, SHUFP_unary_shuffle_mask:$sm)>, +def : Pat<(pshufd:$src2 (bc_v4i32 (memopv4f32 addr:$src1)), (undef)), + (PSHUFDmi addr:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>, Requires<[HasSSE2]>; // Special binary v4i32 shuffle cases with SHUFPS. -def : Pat<(v4i32 (vector_shuffle VR128:$src1, (v4i32 VR128:$src2), - PSHUFD_binary_shuffle_mask:$sm)), - (SHUFPSrri VR128:$src1, VR128:$src2, PSHUFD_binary_shuffle_mask:$sm)>, +def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (v4i32 VR128:$src2))), + (SHUFPSrri VR128:$src1, VR128:$src2, + (SHUFFLE_get_shuf_imm VR128:$src3))>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (vector_shuffle VR128:$src1, - (bc_v4i32 (memopv2i64 addr:$src2)), PSHUFD_binary_shuffle_mask:$sm)), - (SHUFPSrmi VR128:$src1, addr:$src2, PSHUFD_binary_shuffle_mask:$sm)>, +def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (bc_v4i32 (memopv2i64 addr:$src2)))), + (SHUFPSrmi VR128:$src1, addr:$src2, + (SHUFFLE_get_shuf_imm VR128:$src3))>, Requires<[HasSSE2]>; // Special binary v2i64 shuffle cases using SHUFPDrri. -def : Pat<(v2i64 (vector_shuffle VR128:$src1, VR128:$src2, - SHUFP_shuffle_mask:$sm)), - (SHUFPDrri VR128:$src1, VR128:$src2, SHUFP_shuffle_mask:$sm)>, +def : Pat<(v2i64 (shufp:$src3 VR128:$src1, VR128:$src2)), + (SHUFPDrri VR128:$src1, VR128:$src2, + (SHUFFLE_get_shuf_imm VR128:$src3))>, Requires<[HasSSE2]>; -// Special unary SHUFPDrri case. -def : Pat<(v2i64 (vector_shuffle VR128:$src1, (undef), - SHUFP_unary_shuffle_mask:$sm)), - (SHUFPDrri VR128:$src1, VR128:$src1, SHUFP_unary_shuffle_mask:$sm)>, - Requires<[HasSSE2]>; // vector_shuffle v1, , <0, 0, 1, 1, ...> let AddedComplexity = 15 in { -def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), - UNPCKL_v_undef_shuffle_mask:$sm)), - (PSHUFDri VR128:$src, PSHUFD_shuffle_mask:$sm)>, +def : Pat<(v4i32 (unpckl_undef:$src2 VR128:$src, (undef))), + (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, Requires<[OptForSpeed, HasSSE2]>; -def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), - UNPCKL_v_undef_shuffle_mask:$sm)), - (PSHUFDri VR128:$src, PSHUFD_shuffle_mask:$sm)>, +def : Pat<(v4f32 (unpckl_undef:$src2 VR128:$src, (undef))), + (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, Requires<[OptForSpeed, HasSSE2]>; } let AddedComplexity = 10 in { -def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), - UNPCKL_v_undef_shuffle_mask)), +def : Pat<(v4f32 (unpckl_undef VR128:$src, (undef))), (UNPCKLPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; -def : Pat<(v16i8 (vector_shuffle VR128:$src, (undef), - UNPCKL_v_undef_shuffle_mask)), +def : Pat<(v16i8 (unpckl_undef VR128:$src, (undef))), (PUNPCKLBWrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(v8i16 (vector_shuffle VR128:$src, (undef), - UNPCKL_v_undef_shuffle_mask)), +def : Pat<(v8i16 (unpckl_undef VR128:$src, (undef))), (PUNPCKLWDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), - UNPCKL_v_undef_shuffle_mask)), +def : Pat<(v4i32 (unpckl_undef VR128:$src, (undef))), (PUNPCKLDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; } // vector_shuffle v1, , <2, 2, 3, 3, ...> let AddedComplexity = 15 in { -def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), - UNPCKH_v_undef_shuffle_mask:$sm)), - (PSHUFDri VR128:$src, PSHUFD_shuffle_mask:$sm)>, +def : Pat<(v4i32 (unpckh_undef:$src2 VR128:$src, (undef))), + (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, Requires<[OptForSpeed, HasSSE2]>; -def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), - UNPCKH_v_undef_shuffle_mask:$sm)), - (PSHUFDri VR128:$src, PSHUFD_shuffle_mask:$sm)>, +def : Pat<(v4f32 (unpckh_undef:$src2 VR128:$src, (undef))), + (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, Requires<[OptForSpeed, HasSSE2]>; } let AddedComplexity = 10 in { -def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), - UNPCKH_v_undef_shuffle_mask)), +def : Pat<(v4f32 (unpckh_undef VR128:$src, (undef))), (UNPCKHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; -def : Pat<(v16i8 (vector_shuffle VR128:$src, (undef), - UNPCKH_v_undef_shuffle_mask)), +def : Pat<(v16i8 (unpckh_undef VR128:$src, (undef))), (PUNPCKHBWrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(v8i16 (vector_shuffle VR128:$src, (undef), - UNPCKH_v_undef_shuffle_mask)), +def : Pat<(v8i16 (unpckh_undef VR128:$src, (undef))), (PUNPCKHWDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), - UNPCKH_v_undef_shuffle_mask)), +def : Pat<(v4i32 (unpckh_undef VR128:$src, (undef))), (PUNPCKHDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; } let AddedComplexity = 20 in { // vector_shuffle v1, v2 <0, 1, 4, 5> using MOVLHPS -def : Pat<(v4i32 (vector_shuffle VR128:$src1, VR128:$src2, - MOVHP_shuffle_mask)), +def : Pat<(v4i32 (movhp VR128:$src1, VR128:$src2)), (MOVLHPSrr VR128:$src1, VR128:$src2)>; // vector_shuffle v1, v2 <6, 7, 2, 3> using MOVHLPS -def : Pat<(v4i32 (vector_shuffle VR128:$src1, VR128:$src2, - MOVHLPS_shuffle_mask)), +def : Pat<(v4i32 (movhlps VR128:$src1, VR128:$src2)), (MOVHLPSrr VR128:$src1, VR128:$src2)>; // vector_shuffle v1, undef <2, ?, ?, ?> using MOVHLPS -def : Pat<(v4f32 (vector_shuffle VR128:$src1, (undef), - MOVHLPS_v_undef_shuffle_mask)), +def : Pat<(v4f32 (movhlps_undef VR128:$src1, (undef))), (MOVHLPSrr VR128:$src1, VR128:$src1)>; -def : Pat<(v4i32 (vector_shuffle VR128:$src1, (undef), - MOVHLPS_v_undef_shuffle_mask)), +def : Pat<(v4i32 (movhlps_undef VR128:$src1, (undef))), (MOVHLPSrr VR128:$src1, VR128:$src1)>; } let AddedComplexity = 20 in { // vector_shuffle v1, (load v2) <4, 5, 2, 3> using MOVLPS // vector_shuffle v1, (load v2) <0, 1, 4, 5> using MOVHPS -def : Pat<(v4f32 (vector_shuffle VR128:$src1, (load addr:$src2), - MOVLP_shuffle_mask)), +def : Pat<(v4f32 (movlp VR128:$src1, (load addr:$src2))), (MOVLPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE1]>; -def : Pat<(v2f64 (vector_shuffle VR128:$src1, (load addr:$src2), - MOVLP_shuffle_mask)), +def : Pat<(v2f64 (movlp VR128:$src1, (load addr:$src2))), (MOVLPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4f32 (vector_shuffle VR128:$src1, (load addr:$src2), - MOVHP_shuffle_mask)), +def : Pat<(v4f32 (movhp VR128:$src1, (load addr:$src2))), (MOVHPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE1]>; -def : Pat<(v2f64 (vector_shuffle VR128:$src1, (load addr:$src2), - MOVHP_shuffle_mask)), +def : Pat<(v2f64 (movhp VR128:$src1, (load addr:$src2))), (MOVHPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (vector_shuffle VR128:$src1, (load addr:$src2), - MOVLP_shuffle_mask)), +def : Pat<(v4i32 (movlp VR128:$src1, (load addr:$src2))), (MOVLPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v2i64 (vector_shuffle VR128:$src1, (load addr:$src2), - MOVLP_shuffle_mask)), +def : Pat<(v2i64 (movlp VR128:$src1, (load addr:$src2))), (MOVLPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (vector_shuffle VR128:$src1, (load addr:$src2), - MOVHP_shuffle_mask)), +def : Pat<(v4i32 (movhp VR128:$src1, (load addr:$src2))), (MOVHPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE1]>; -def : Pat<(v2i64 (vector_shuffle VR128:$src1, (load addr:$src2), - MOVHP_shuffle_mask)), +def : Pat<(v2i64 (movhp VR128:$src1, (load addr:$src2))), (MOVHPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; } // (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS // (store (vector_shuffle (load addr), v2, <0, 1, 4, 5>), addr) using MOVHPS -def : Pat<(store (v4f32 (vector_shuffle (load addr:$src1), VR128:$src2, - MOVLP_shuffle_mask)), addr:$src1), +def : Pat<(store (v4f32 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; -def : Pat<(store (v2f64 (vector_shuffle (load addr:$src1), VR128:$src2, - MOVLP_shuffle_mask)), addr:$src1), +def : Pat<(store (v2f64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(store (v4f32 (vector_shuffle (load addr:$src1), VR128:$src2, - MOVHP_shuffle_mask)), addr:$src1), +def : Pat<(store (v4f32 (movhp (load addr:$src1), VR128:$src2)), addr:$src1), (MOVHPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; -def : Pat<(store (v2f64 (vector_shuffle (load addr:$src1), VR128:$src2, - MOVHP_shuffle_mask)), addr:$src1), +def : Pat<(store (v2f64 (movhp (load addr:$src1), VR128:$src2)), addr:$src1), (MOVHPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(store (v4i32 (vector_shuffle - (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2, - MOVLP_shuffle_mask)), addr:$src1), +def : Pat<(store (v4i32 (movlp (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)), + addr:$src1), (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; -def : Pat<(store (v2i64 (vector_shuffle (load addr:$src1), VR128:$src2, - MOVLP_shuffle_mask)), addr:$src1), +def : Pat<(store (v2i64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(store (v4i32 (vector_shuffle - (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2, - MOVHP_shuffle_mask)), addr:$src1), +def : Pat<(store (v4i32 (movhp (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)), + addr:$src1), (MOVHPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; -def : Pat<(store (v2i64 (vector_shuffle (load addr:$src1), VR128:$src2, - MOVHP_shuffle_mask)), addr:$src1), +def : Pat<(store (v2i64 (movhp (load addr:$src1), VR128:$src2)), addr:$src1), (MOVHPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; let AddedComplexity = 15 in { // Setting the lowest element in the vector. -def : Pat<(v4i32 (vector_shuffle VR128:$src1, VR128:$src2, - MOVL_shuffle_mask)), +def : Pat<(v4i32 (movl VR128:$src1, VR128:$src2)), (MOVLPSrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v2i64 (vector_shuffle VR128:$src1, VR128:$src2, - MOVL_shuffle_mask)), +def : Pat<(v2i64 (movl VR128:$src1, VR128:$src2)), (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; // vector_shuffle v1, v2 <4, 5, 2, 3> using MOVLPDrr (movsd) -def : Pat<(v4f32 (vector_shuffle VR128:$src1, VR128:$src2, - MOVLP_shuffle_mask)), +def : Pat<(v4f32 (movlp VR128:$src1, VR128:$src2)), (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (vector_shuffle VR128:$src1, VR128:$src2, - MOVLP_shuffle_mask)), +def : Pat<(v4i32 (movlp VR128:$src1, VR128:$src2)), (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; } // Set lowest element and zero upper elements. let AddedComplexity = 15 in -def : Pat<(v2f64 (vector_shuffle immAllZerosV_bc, VR128:$src, - MOVL_shuffle_mask)), +def : Pat<(v2f64 (movl immAllZerosV_bc, VR128:$src)), (MOVZPQILo2PQIrr VR128:$src)>, Requires<[HasSSE2]>; def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))), (MOVZPQILo2PQIrr VR128:$src)>, Requires<[HasSSE2]>; Modified: llvm/trunk/test/CodeGen/X86/vec_clear.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_clear.ll?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_clear.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_clear.ll Thu Apr 23 22:42:54 2009 @@ -1,5 +1,7 @@ -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin | not grep and -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin | grep psrldq +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin -o %t -f +; RUN: not grep and %t +; RUN: not grep psrldq %t +; RUN: grep xorps %t define <4 x float> @test(<4 x float>* %v1) nounwind { %tmp = load <4 x float>* %v1 ; <<4 x float>> [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll Thu Apr 23 22:42:54 2009 @@ -1,9 +1,7 @@ -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | \ -; RUN: grep unpcklps | count 1 -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | \ -; RUN: grep unpckhps | count 1 -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | \ -; RUN: not grep {sub.*esp} +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -o %t -f +; RUN: grep unpcklps %t | count 1 +; RUN: grep pshufd %t | count 1 +; RUN: not grep {sub.*esp} %t define void @test(<4 x float>* %res, <4 x float>* %A, <4 x float>* %B) { %tmp = load <4 x float>* %B ; <<4 x float>> [#uses=2] Modified: llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll Thu Apr 23 22:42:54 2009 @@ -1,8 +1,10 @@ -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse,-sse2 | grep shufps | count 4 -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse,-sse2 -mtriple=i386-apple-darwin | grep mov | count 2 -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | grep pshufd | count 4 -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | not grep shufps -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin | not grep mov +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse,-sse2 -mtriple=i386-apple-darwin -o %t -f +; RUN: grep shufps %t | count 4 +; RUN: grep movaps %t | count 2 +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin -o %t -f +; RUN: grep pshufd %t | count 4 +; RUN: not grep shufps %t +; RUN: not grep mov %t define <4 x float> @t1(<4 x float> %a, <4 x float> %b) nounwind { %tmp1 = shufflevector <4 x float> %b, <4 x float> undef, <4 x i32> zeroinitializer Modified: llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll Thu Apr 23 22:42:54 2009 @@ -1,8 +1,7 @@ ; RUN: llvm-as < %s | llc -march=x86 -mattr=sse41 -disable-mmx -o %t -f ; RUN: grep pshufhw %t | grep 161 | count 1 -; RUN: grep pslldq %t | count 1 - - +; RUN: grep shufps %t | count 1 +; RUN: not grep pslldq %t ; Test case when creating pshufhw, we incorrectly set the higher order bit ; for an undef, @@ -20,4 +19,4 @@ %0 = shufflevector <4 x i32> %in, <4 x i32> , <4 x i32> < i32 undef, i32 5, i32 undef, i32 2> store <4 x i32> %0, <4 x i32>* %dest ret void -} \ No newline at end of file +} Modified: llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll Thu Apr 23 22:42:54 2009 @@ -1,6 +1,6 @@ ; RUN: llvm-as < %s | llc -march=x86 -mcpu=yonah -o %t -f ; RUN: grep pextrw %t | count 1 -; RUN: grep punpcklqdq %t | count 1 +; RUN: grep movlhps %t | count 1 ; RUN: grep pshufhw %t | count 1 ; RUN: grep pinsrw %t | count 1 ; RUN: llvm-as < %s | llc -march=x86 -mcpu=core2 -o %t -f Modified: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp (original) +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp Thu Apr 23 22:42:54 2009 @@ -194,10 +194,6 @@ ConstraintType = SDTCisOpSmallerThanOp; x.SDTCisOpSmallerThanOp_Info.BigOperandNum = R->getValueAsInt("BigOperandNum"); - } else if (R->isSubClassOf("SDTCisIntVectorOfSameSize")) { - ConstraintType = SDTCisIntVectorOfSameSize; - x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum = - R->getValueAsInt("OtherOpNum"); } else if (R->isSubClassOf("SDTCisEltOfVec")) { ConstraintType = SDTCisEltOfVec; x.SDTCisEltOfVec_Info.OtherOperandNum = @@ -365,23 +361,9 @@ } return MadeChange; } - case SDTCisIntVectorOfSameSize: { - TreePatternNode *OtherOperand = - getOperandNum(x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum, - N, NumResults); - if (OtherOperand->hasTypeSet()) { - if (!isVector(OtherOperand->getTypeNum(0))) - TP.error(N->getOperator()->getName() + " VT operand must be a vector!"); - MVT IVT = OtherOperand->getTypeNum(0); - unsigned NumElements = IVT.getVectorNumElements(); - IVT = MVT::getIntVectorWithNumElements(NumElements); - return NodeToApply->UpdateNodeType(IVT.getSimpleVT(), TP); - } - return false; - } case SDTCisEltOfVec: { TreePatternNode *OtherOperand = - getOperandNum(x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum, + getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NumResults); if (OtherOperand->hasTypeSet()) { if (!isVector(OtherOperand->getTypeNum(0))) @@ -925,25 +907,6 @@ if (NI.getNumResults() == 0) MadeChange |= UpdateNodeType(MVT::isVoid, TP); - // If this is a vector_shuffle operation, apply types to the build_vector - // operation. The types of the integers don't matter, but this ensures they - // won't get checked. - if (getOperator()->getName() == "vector_shuffle" && - getChild(2)->getOperator()->getName() == "build_vector") { - TreePatternNode *BV = getChild(2); - const std::vector &LegalVTs - = CDP.getTargetInfo().getLegalValueTypes(); - MVT::SimpleValueType LegalIntVT = MVT::Other; - for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i) - if (isInteger(LegalVTs[i]) && !isVector(LegalVTs[i])) { - LegalIntVT = LegalVTs[i]; - break; - } - assert(LegalIntVT != MVT::Other && "No legal integer VT?"); - - for (unsigned i = 0, e = BV->getNumChildren(); i != e; ++i) - MadeChange |= BV->getChild(i)->UpdateNodeType(LegalIntVT, TP); - } return MadeChange; } else if (getOperator()->isSubClassOf("Instruction")) { const DAGInstruction &Inst = CDP.getInstruction(getOperator()); @@ -2086,6 +2049,9 @@ IterateInference |= Result->getTree(0)-> UpdateNodeType(Pattern->getTree(0)->getExtTypes(), *Result); } while (IterateInference); + + // Blah? + Result->getTree(0)->setTransformFn(Pattern->getTree(0)->getTransformFn()); // Verify that we inferred enough types that we can do something with the // pattern and result. If these fire the user has to add type casts. Modified: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h?rev=69952&r1=69951&r2=69952&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h (original) +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h Thu Apr 23 22:42:54 2009 @@ -62,8 +62,7 @@ unsigned OperandNo; // The operand # this constraint applies to. enum { SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisSameAs, - SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisIntVectorOfSameSize, - SDTCisEltOfVec + SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec } ConstraintType; union { // The discriminated union. @@ -81,9 +80,6 @@ } SDTCisOpSmallerThanOp_Info; struct { unsigned OtherOperandNum; - } SDTCisIntVectorOfSameSize_Info; - struct { - unsigned OtherOperandNum; } SDTCisEltOfVec_Info; } x; From benny.kra at googlemail.com Thu Apr 23 13:52:40 2009 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Thu, 23 Apr 2009 20:52:40 +0200 Subject: [llvm-commits] [PATCH] Makfile: force svn locale to C Message-ID: <803B1121-D7D9-4F51-9858-2273778DAC76@gmail.com> If some LC_* env variables are set they will override LANG. Use LC_ALL instead to override all LC_* vars (and LANG). -------------- next part -------------- A non-text attachment was scrubbed... Name: locale.patch Type: application/octet-stream Size: 390 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090423/be18f2fd/attachment.obj -------------- next part -------------- From stoklund at 2pi.dk Fri Apr 24 00:19:07 2009 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Fri, 24 Apr 2009 07:19:07 +0200 Subject: [llvm-commits] [PATCH] Don't -join-cross-class-copies of physical and virtual registers In-Reply-To: <22FEC6A4-57A8-44E5-8844-79E3056D8A13@apple.com> References: <60BF6861-E1DC-4FFC-904C-E301710F4908@2pi.dk> <22FEC6A4-57A8-44E5-8844-79E3056D8A13@apple.com> Message-ID: <1B72D853-F576-4596-929E-FB89182E772F@2pi.dk> On 23/04/2009, at 22.40, Evan Cheng wrote: > Unfortunately your patch will disable some of the functionalities for > X86. See the comments: > > // This is not an insert_subreg but it looks like one. > // e.g. %reg1024:4 = MOV32rr %EAX > > That means reg1024 is a 64-bit register. EAX is not in the register > class but we want to coalesce this by assigning RAX to reg1024. I don't know how I managed to overlook that. Thanks. It seems there are two orthogonal issues here. One is the use of subreg operands, the other is register classes. Both can be relevant at the same time. For instance > %reg1024:4 = MOV32rr %ESI would be illegal to coalesce if %reg1024 is GR64_. The subregister %reg1024:4 has class GR32_, and %ESI is not in that class. With the current check in differingRegisterClasses, could this be accidentally coalesced?: %reg1024:1 = MOV8rr %reg1025:2 If both registers are GR16_, differingRegisterClasses returns false. > Can you find another solution? Yes. I will have another go. I think the issue of subreg operands and that of regclasses should be handled separately. Thanks again, /jakob From clattner at apple.com Fri Apr 24 00:29:15 2009 From: clattner at apple.com (Chris Lattner) Date: Thu, 23 Apr 2009 22:29:15 -0700 Subject: [llvm-commits] [llvm-gcc-4.2] r69795 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp In-Reply-To: <46672C4C-8B30-4C11-88A9-014EADD32FB7@apple.com> References: <200904220928.n3M9SRbC004234@zion.cs.uiuc.edu> <200904231003.37841.baldrick@free.fr> <17D0DDD6-5B1E-48FE-919D-11FB8FA93FC2@apple.com> <0D37D7F2-8DC9-42D6-B9B1-F64F9C003EEA@apple.com> <46672C4C-8B30-4C11-88A9-014EADD32FB7@apple.com> Message-ID: On Apr 23, 2009, at 4:53 PM, Dale Johannesen wrote: >>> >>> A C++ test affected by this bug is g++.old-deja/g++.jason/bool2.C . >>> I'll put it in the llvm testsuite. >> >> Ah, nice, thanks Dale! Can you verify that the correct code is >> generated on ppc for it? > > Yes, it is. Awesome, thanks Duncan and Dale! -Chris From sabre at nondot.org Fri Apr 24 00:30:14 2009 From: sabre at nondot.org (Chris Lattner) Date: Fri, 24 Apr 2009 05:30:14 -0000 Subject: [llvm-commits] [llvm] r69958 - in /llvm/trunk: include/llvm/Constants.h unittests/VMCore/ConstantsTest.cpp Message-ID: <200904240530.n3O5UEMK005367@zion.cs.uiuc.edu> Author: lattner Date: Fri Apr 24 00:30:14 2009 New Revision: 69958 URL: http://llvm.org/viewvc/llvm-project?rev=69958&view=rev Log: "I got annoyed at the compiler warnings from ConstantInt::get(Ty, -1, true), and casts make me nervous and are verbose anyway, so here's a ConstantInt::getSigned(Ty, int64_t) method. Just overloading ConstantInt::get() to take an int64_t too would cause ambiguous overload errors." Patch by Jeffrey Yasskin! Modified: llvm/trunk/include/llvm/Constants.h llvm/trunk/unittests/VMCore/ConstantsTest.cpp Modified: llvm/trunk/include/llvm/Constants.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=69958&r1=69957&r2=69958&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constants.h (original) +++ llvm/trunk/include/llvm/Constants.h Fri Apr 24 00:30:14 2009 @@ -110,6 +110,15 @@ /// @brief Get a ConstantInt for a specific value. static ConstantInt *get(const Type *Ty, uint64_t V, bool isSigned = false); + /// Return a ConstantInt with the specified value for the specified type. The + /// value V will be canonicalized to a an unsigned APInt. Accessing it with + /// either getSExtValue() or getZExtValue() will yield a correctly sized and + /// signed value for the type Ty. + /// @brief Get a ConstantInt for a specific signed value. + static ConstantInt *getSigned(const Type *Ty, int64_t V) { + return get(Ty, V, true); + } + /// Return a ConstantInt with the specified value and an implied Type. The /// type is the integer type that corresponds to the bit width of the value. static ConstantInt *get(const APInt &V); Modified: llvm/trunk/unittests/VMCore/ConstantsTest.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/VMCore/ConstantsTest.cpp?rev=69958&r1=69957&r2=69958&view=diff ============================================================================== --- llvm/trunk/unittests/VMCore/ConstantsTest.cpp (original) +++ llvm/trunk/unittests/VMCore/ConstantsTest.cpp Fri Apr 24 00:30:14 2009 @@ -19,6 +19,7 @@ Constant* One = ConstantInt::get(Int1, 1, true); Constant* Zero = ConstantInt::get(Int1, 0); Constant* NegOne = ConstantInt::get(Int1, static_cast(-1), true); + EXPECT_EQ(NegOne, ConstantInt::getSigned(Int1, -1)); Constant* Undef = UndefValue::get(Int1); // Input: @b = constant i1 add(i1 1 , i1 1) @@ -94,5 +95,18 @@ EXPECT_EQ(Zero, ConstantExpr::getSRem(One, NegOne)); } +TEST(ConstantsTest, IntSigns) { + const IntegerType* Int8Ty = Type::Int8Ty; + EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, false)->getSExtValue()); + EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, true)->getSExtValue()); + EXPECT_EQ(100, ConstantInt::getSigned(Int8Ty, 100)->getSExtValue()); + EXPECT_EQ(-50, ConstantInt::get(Int8Ty, 206)->getSExtValue()); + EXPECT_EQ(-50, ConstantInt::getSigned(Int8Ty, -50)->getSExtValue()); + EXPECT_EQ(206U, ConstantInt::getSigned(Int8Ty, -50)->getZExtValue()); + + // Overflow is handled by truncation. + EXPECT_EQ(0x3b, ConstantInt::get(Int8Ty, 0x13b)->getSExtValue()); +} + } // end anonymous namespace } // end namespace llvm From clattner at apple.com Fri Apr 24 00:31:07 2009 From: clattner at apple.com (Chris Lattner) Date: Thu, 23 Apr 2009 22:31:07 -0700 Subject: [llvm-commits] Add ConstantInt::getSigned() In-Reply-To: References: Message-ID: On Apr 23, 2009, at 6:26 PM, Jeffrey Yasskin wrote: > I got annoyed at the compiler warnings from ConstantInt::get(Ty, -1, > true), and casts make me nervous and are verbose anyway, so here's a > ConstantInt::getSigned(Ty, int64_t) method. Just overloading > ConstantInt::get() to take an int64_t too would cause ambiguous > overload errors. Applied, thanks: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20090420/076643.html -Chris From clattner at apple.com Fri Apr 24 00:32:39 2009 From: clattner at apple.com (Chris Lattner) Date: Thu, 23 Apr 2009 22:32:39 -0700 Subject: [llvm-commits] [PATCH] Makfile: force svn locale to C In-Reply-To: <803B1121-D7D9-4F51-9858-2273778DAC76@gmail.com> References: <803B1121-D7D9-4F51-9858-2273778DAC76@gmail.com> Message-ID: On Apr 23, 2009, at 11:52 AM, Benjamin Kramer wrote: > If some LC_* env variables are set they will override LANG. Use > LC_ALL instead to override all LC_* vars (and LANG). Gabor, this seems fine to me, does this look ok to you? If so, please apply it, thanks! -Chris From baldrick at free.fr Fri Apr 24 01:16:31 2009 From: baldrick at free.fr (Duncan Sands) Date: Fri, 24 Apr 2009 08:16:31 +0200 Subject: [llvm-commits] [llvm] r69958 - in /llvm/trunk: include/llvm/Constants.h unittests/VMCore/ConstantsTest.cpp In-Reply-To: <200904240530.n3O5UEMK005367@zion.cs.uiuc.edu> References: <200904240530.n3O5UEMK005367@zion.cs.uiuc.edu> Message-ID: <200904240816.31536.baldrick@free.fr> > + /// value V will be canonicalized to a an unsigned APInt. Accessing it with a an -> an Ciao, Duncan. From baldrick at free.fr Fri Apr 24 01:20:11 2009 From: baldrick at free.fr (Duncan Sands) Date: Fri, 24 Apr 2009 08:20:11 +0200 Subject: [llvm-commits] [llvm] r69948 - /llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp In-Reply-To: <200904240240.n3O2eNMY032245@zion.cs.uiuc.edu> References: <200904240240.n3O2eNMY032245@zion.cs.uiuc.edu> Message-ID: <200904240820.11695.baldrick@free.fr> Hi Dan, > Instead of requiring TLI.LowerCallTo to return an ISD::BUILD_PAIR, > use ISD::EXTRACT_ELEMENT. SelectionDAG has a special fast-path for > the cast of an EXTRACT_ELEMENT with a BUILD_PAIR operand, for the > common case. maybe these routines could be factorized somehow? Ciao, Duncan. From sabre at nondot.org Fri Apr 24 01:37:12 2009 From: sabre at nondot.org (Chris Lattner) Date: Fri, 24 Apr 2009 06:37:12 -0000 Subject: [llvm-commits] [llvm] r69962 - /llvm/trunk/include/llvm/Constants.h Message-ID: <200904240637.n3O6bCWR007381@zion.cs.uiuc.edu> Author: lattner Date: Fri Apr 24 01:37:12 2009 New Revision: 69962 URL: http://llvm.org/viewvc/llvm-project?rev=69962&view=rev Log: fix a typo noticed by duncan Modified: llvm/trunk/include/llvm/Constants.h Modified: llvm/trunk/include/llvm/Constants.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=69962&r1=69961&r2=69962&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constants.h (original) +++ llvm/trunk/include/llvm/Constants.h Fri Apr 24 01:37:12 2009 @@ -104,7 +104,7 @@ } /// Return a ConstantInt with the specified value for the specified type. The - /// value V will be canonicalized to a an unsigned APInt. Accessing it with + /// value V will be canonicalized to an unsigned APInt. Accessing it with /// either getSExtValue() or getZExtValue() will yield a correctly sized and /// signed value for the type Ty. /// @brief Get a ConstantInt for a specific value. From baldrick at free.fr Fri Apr 24 04:18:32 2009 From: baldrick at free.fr (Duncan Sands) Date: Fri, 24 Apr 2009 11:18:32 +0200 Subject: [llvm-commits] [llvm] r69952 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/CellSPU/ lib/Target/PowerPC/ lib/Target/X86/ test/CodeGen/X86/ utils/TableGen/ In-Reply-To: <200904240343.n3O3h13J001960@zion.cs.uiuc.edu> References: <200904240343.n3O3h13J001960@zion.cs.uiuc.edu> Message-ID: <200904241118.33846.baldrick@free.fr> Hi Nate, thanks for doing this. > +class ShuffleVectorSDNode : public SDNode { > + SDUse Ops[2]; > + int *Mask; > +protected: > + friend class SelectionDAG; > + ShuffleVectorSDNode(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, int *M) > + : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) { > + InitOperands(Ops, N1, N2); > + } > +public: > + > + const int * getMask() const { return Mask; } It would be easy to go off the end of the mask when accessing mask elements. How about having methods to access individual mask elements, or turn Mask into a {int *, size} pair, which accessors that check for overflow? > - unsigned Idx = cast(InVec.getOperand(2). > - getOperand(Elt))->getZExtValue(); > - unsigned NumElems = InVec.getOperand(2).getNumOperands(); > + int Idx = cast(InVec)->getMask()[Elt]; > + int NumElems = InVec.getValueType().getVectorNumElements(); What happens here if Idx < 0? > SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { > - SDValue ShufMask = N->getOperand(2); > - unsigned NumElts = ShufMask.getNumOperands(); > + return SDValue(); > + > + MVT VT = N->getValueType(0); > + unsigned NumElts = VT.getVectorNumElements(); Isn't this code unreachable since you always return SDValue()? > @@ -762,12 +769,6 @@ > assert(N->getValueType(0).isVector() && "Wrong return type!"); > assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() && > "Wrong number of operands!"); > - MVT EltVT = N->getValueType(0).getVectorElementType(); > - for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) > - assert((I->getValueType() == EltVT || > - (EltVT.isInteger() && I->getValueType().isInteger() && > - EltVT.bitsLE(I->getValueType()))) && > - "Wrong operand type!"); Why are you removing this assertion? > + // Validate that all the indices past in in Mask are within the range of past in in -> passed in > + // elements input to the shuffle. > + int NElts = VT.getVectorNumElements(); > + SmallVector MaskVec; > + for (int i = 0; i != NElts; ++i) { > + if (Mask[i] >= (NElts * 2)) { > + assert(0 && "Index out of range"); > + return SDValue(); > + } > + MaskVec.push_back(Mask[i]); > + } You should probably also check that any negative values are actually equal to -1. > + // Canonicalize all index into lhs, -> shuffle lhs, undef > + // Canonicalize all index into rhs, -> shuffle rhs, undef > + bool AllLHS = true, AllRHS = true; > + bool N2Undef = N2.getOpcode() == ISD::UNDEF; > + for (int i = 0; i != NElts; ++i) { > + if (MaskVec[i] >= NElts) { > + if (N2Undef) > + MaskVec[i] = -1; > + else > + AllLHS = false; > + } else if (MaskVec[i] >= 0) { > + AllRHS = false; > + } Don't you also want to do something special if N1 is undef? Also, you can do an early exit if both AllLHS and AllRHS are false. > + // If Identity shuffle, or all shuffle in to undef, return that node. > + bool AllUndef = true; > + bool Identity = true; > + for (int i = 0; i < NElts; ++i) { > + if (MaskVec[i] >= 0 && MaskVec[i] != i) Identity = false; > + if (MaskVec[i] >= 0) AllUndef = false; > + } You can do an early exit if both Identity and AllUndef are false. > + // Blah? > + Result->getTree(0)->setTransformFn(Pattern->getTree(0)->getTransformFn()); What's this bit about? I didn't check the target specific code. Thanks again for doing this! Ciao, Duncan. From duncan.sands at math.u-psud.fr Fri Apr 24 04:24:50 2009 From: duncan.sands at math.u-psud.fr (Duncan Sands) Date: Fri, 24 Apr 2009 11:24:50 +0200 Subject: [llvm-commits] [llvm] r69952 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/CellSPU/ lib/Target/PowerPC/ lib/Target/X86/ test/CodeGen/X86/ utils/TableGen/ In-Reply-To: <200904240343.n3O3h13J001960@zion.cs.uiuc.edu> References: <200904240343.n3O3h13J001960@zion.cs.uiuc.edu> Message-ID: <200904241124.51230.duncan.sands@math.u-psud.fr> Hi Nate, I'm seeing these testsuite failures on x86-64 linux: ... FAIL: llvm/test/CodeGen/Generic/vector-casts.ll for PR2671 Failed with signal(SIGSEGV) at line 1 ... FAIL: llvm/test/CodeGen/X86/mmx-arith.ll Failed with signal(SIGSEGV) at line 1 FAIL: llvm/test/CodeGen/X86/vec_set.ll Failed with exit(1) at line 1 while running: llvm-as < llvm/test/CodeGen/X86/vec_set.ll | llc -march=x86 -mattr=+sse2 | /bin/grep punpckl | count 7 count: expected 7 lines and got 0. ... FAIL: llvm/test/CodeGen/X86/vec_shuffle-6.ll Failed with exit(1) at line 3 while running: grep movaps vec_shuffle-6.ll.tmp | count 1 count: expected 1 lines and got 0. Ciao, Duncan. From rafael.espindola at gmail.com Fri Apr 24 07:40:45 2009 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Fri, 24 Apr 2009 12:40:45 -0000 Subject: [llvm-commits] [llvm] r69967 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/CellSPU/ lib/Target/PowerPC/ lib/Target/X86/ test/CodeGen/X86/ utils/TableGen/ Message-ID: <200904241240.n3OCenYU030599@zion.cs.uiuc.edu> Author: rafael Date: Fri Apr 24 07:40:33 2009 New Revision: 69967 URL: http://llvm.org/viewvc/llvm-project?rev=69967&view=rev Log: Revert 69952. Causes testsuite failures on linux x86-64. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h llvm/trunk/include/llvm/Target/TargetLowering.h llvm/trunk/include/llvm/Target/TargetSelectionDAG.td llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86ISelLowering.h llvm/trunk/lib/Target/X86/X86InstrInfo.td llvm/trunk/lib/Target/X86/X86InstrMMX.td llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/test/CodeGen/X86/vec_clear.ll llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Fri Apr 24 07:40:33 2009 @@ -353,13 +353,6 @@ SDValue getConvertRndSat(MVT VT, DebugLoc dl, SDValue Val, SDValue DTy, SDValue STy, SDValue Rnd, SDValue Sat, ISD::CvtCode Code); - - /// getVectorShuffle - Return an ISD::VECTOR_SHUFFLE node. The number of - /// elements in VT, which must be a vector type, must match the number of - /// mask elements NumElts. A negative integer mask element is treated as - /// undefined. - SDValue getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, - const int *MaskElts); /// getZeroExtendInReg - Return the expression required to zero extend the Op /// value assuming it was the smaller SrcTy value. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Fri Apr 24 07:40:33 2009 @@ -1703,32 +1703,6 @@ } }; -class ShuffleVectorSDNode : public SDNode { - SDUse Ops[2]; - int *Mask; -protected: - friend class SelectionDAG; - ShuffleVectorSDNode(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, int *M) - : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) { - InitOperands(Ops, N1, N2); - } -public: - - const int * getMask() const { return Mask; } - - bool isSplat() { return isSplatMask(Mask, getValueType(0)); } - int getSplatIndex() { - assert(isSplat() && "Cannot get splat index for non-splat!"); - return Mask[0]; - } - static bool isSplatMask(const int *Mask, MVT VT); - - static bool classof(const ShuffleVectorSDNode *) { return true; } - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::VECTOR_SHUFFLE; - } -}; - class ConstantSDNode : public SDNode { const ConstantInt *Value; friend class SelectionDAG; @@ -2110,7 +2084,7 @@ return N->getOpcode() == ISD::CONDCODE; } }; - + /// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the /// future and most targets don't support it. class CvtRndSatSDNode : public SDNode { Modified: llvm/trunk/include/llvm/Target/TargetLowering.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetLowering.h (original) +++ llvm/trunk/include/llvm/Target/TargetLowering.h Fri Apr 24 07:40:33 2009 @@ -328,7 +328,7 @@ /// support *some* VECTOR_SHUFFLE operations, those with specific masks. /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values /// are assumed to be legal. - virtual bool isShuffleMaskLegal(const int *Mask, MVT VT) const { + virtual bool isShuffleMaskLegal(SDValue Mask, MVT VT) const { return true; } @@ -336,7 +336,9 @@ /// used by Targets can use this to indicate if there is a suitable /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant /// pool entry. - virtual bool isVectorClearMaskLegal(const int *Mask, MVT VT) const { + virtual bool isVectorClearMaskLegal(const std::vector &BVOps, + MVT EVT, + SelectionDAG &DAG) const { return false; } Modified: llvm/trunk/include/llvm/Target/TargetSelectionDAG.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetSelectionDAG.td?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetSelectionDAG.td (original) +++ llvm/trunk/include/llvm/Target/TargetSelectionDAG.td Fri Apr 24 07:40:33 2009 @@ -51,6 +51,15 @@ int BigOperandNum = BigOp; } +/// SDTCisIntVectorOfSameSize - This indicates that ThisOp and OtherOp are +/// vector types, and that ThisOp is the result of +/// MVT::getIntVectorWithNumElements with the number of elements +/// that ThisOp has. +class SDTCisIntVectorOfSameSize + : SDTypeConstraint { + int OtherOpNum = OtherOp; +} + /// SDTCisEltOfVec - This indicates that ThisOp is a scalar type of the same /// type as the element type of OtherOp, which is a vector type. class SDTCisEltOfVec @@ -166,8 +175,8 @@ SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3> ]>; -def SDTVecShuffle : SDTypeProfile<1, 2, [ - SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> +def SDTVecShuffle : SDTypeProfile<1, 3, [ + SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisIntVectorOfSameSize<3, 0> ]>; def SDTVecExtract : SDTypeProfile<1, 2, [ // vector extract SDTCisEltOfVec<0, 1>, SDTCisPtrTy<2> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Fri Apr 24 07:40:33 2009 @@ -5098,21 +5098,7 @@ return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), InVec.getValueType(), &Ops[0], Ops.size()); } - // If the invec is an UNDEF and if EltNo is a constant, create a new - // BUILD_VECTOR with undef elements and the inserted element. - if (!LegalOperations && InVec.getOpcode() == ISD::UNDEF && - isa(EltNo)) { - MVT VT = InVec.getValueType(); - MVT EVT = VT.getVectorElementType(); - unsigned NElts = VT.getVectorNumElements(); - SmallVector Ops(NElts, DAG.getUNDEF(EVT)); - unsigned Elt = cast(EltNo)->getZExtValue(); - if (Elt < Ops.size()) - Ops[Elt] = InVal; - return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), - InVec.getValueType(), &Ops[0], Ops.size()); - } return SDValue(); } @@ -5174,8 +5160,9 @@ // to examine the mask. if (BCNumEltsChanged) return SDValue(); - int Idx = cast(InVec)->getMask()[Elt]; - int NumElems = InVec.getValueType().getVectorNumElements(); + unsigned Idx = cast(InVec.getOperand(2). + getOperand(Elt))->getZExtValue(); + unsigned NumElems = InVec.getOperand(2).getNumOperands(); InVec = (Idx < NumElems) ? InVec.getOperand(0) : InVec.getOperand(1); if (InVec.getOpcode() == ISD::BIT_CONVERT) InVec = InVec.getOperand(0); @@ -5222,6 +5209,7 @@ SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *N) { unsigned NumInScalars = N->getNumOperands(); MVT VT = N->getValueType(0); + unsigned NumElts = VT.getVectorNumElements(); MVT EltType = VT.getVectorElementType(); // Check to see if this is a BUILD_VECTOR of a bunch of EXTRACT_VECTOR_ELT @@ -5264,36 +5252,56 @@ } // If everything is good, we can make a shuffle operation. + MVT IndexVT = MVT::i32; if (VecIn1.getNode()) { - SmallVector Mask; + SmallVector BuildVecIndices; for (unsigned i = 0; i != NumInScalars; ++i) { if (N->getOperand(i).getOpcode() == ISD::UNDEF) { - Mask.push_back(-1); + BuildVecIndices.push_back(DAG.getUNDEF(IndexVT)); continue; } - // If extracting from the first vector, just use the index directly. SDValue Extract = N->getOperand(i); + + // If extracting from the first vector, just use the index directly. SDValue ExtVal = Extract.getOperand(1); if (Extract.getOperand(0) == VecIn1) { - Mask.push_back(cast(ExtVal)->getZExtValue()); + if (ExtVal.getValueType() == IndexVT) + BuildVecIndices.push_back(ExtVal); + else { + unsigned Idx = cast(ExtVal)->getZExtValue(); + BuildVecIndices.push_back(DAG.getConstant(Idx, IndexVT)); + } continue; } // Otherwise, use InIdx + VecSize unsigned Idx = cast(ExtVal)->getZExtValue(); - Mask.push_back(Idx+NumInScalars); + BuildVecIndices.push_back(DAG.getConstant(Idx+NumInScalars, IndexVT)); } // Add count and size info. - if (!TLI.isTypeLegal(VT) && LegalTypes) + MVT BuildVecVT = MVT::getVectorVT(IndexVT, NumElts); + if (!TLI.isTypeLegal(BuildVecVT) && LegalTypes) return SDValue(); // Return the new VECTOR_SHUFFLE node. - SDValue Ops[2]; + SDValue Ops[5]; Ops[0] = VecIn1; - Ops[1] = VecIn2.getNode() ? VecIn2 : DAG.getUNDEF(VT); - return DAG.getVectorShuffle(VT, N->getDebugLoc(), Ops[0], Ops[1], &Mask[0]); + if (VecIn2.getNode()) { + Ops[1] = VecIn2; + } else { + // Use an undef build_vector as input for the second operand. + std::vector UnOps(NumInScalars, + DAG.getUNDEF(EltType)); + Ops[1] = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT, + &UnOps[0], UnOps.size()); + AddToWorkList(Ops[1].getNode()); + } + + Ops[2] = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), BuildVecVT, + &BuildVecIndices[0], BuildVecIndices.size()); + return DAG.getNode(ISD::VECTOR_SHUFFLE, N->getDebugLoc(), VT, Ops, 3); } return SDValue(); @@ -5313,10 +5321,8 @@ } SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { - return SDValue(); - - MVT VT = N->getValueType(0); - unsigned NumElts = VT.getVectorNumElements(); + SDValue ShufMask = N->getOperand(2); + unsigned NumElts = ShufMask.getNumOperands(); SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -5324,13 +5330,60 @@ assert(N0.getValueType().getVectorNumElements() == NumElts && "Vector shuffle must be normalized in DAG"); - // FIXME: implement canonicalizations from DAG.getVectorShuffle() + // If the shuffle mask is an identity operation on the LHS, return the LHS. + bool isIdentity = true; + for (unsigned i = 0; i != NumElts; ++i) { + if (ShufMask.getOperand(i).getOpcode() != ISD::UNDEF && + cast(ShufMask.getOperand(i))->getZExtValue() != i) { + isIdentity = false; + break; + } + } + if (isIdentity) return N->getOperand(0); + + // If the shuffle mask is an identity operation on the RHS, return the RHS. + isIdentity = true; + for (unsigned i = 0; i != NumElts; ++i) { + if (ShufMask.getOperand(i).getOpcode() != ISD::UNDEF && + cast(ShufMask.getOperand(i))->getZExtValue() != + i+NumElts) { + isIdentity = false; + break; + } + } + if (isIdentity) return N->getOperand(1); + + // Check if the shuffle is a unary shuffle, i.e. one of the vectors is not + // needed at all. + bool isUnary = true; + bool isSplat = true; + int VecNum = -1; + unsigned BaseIdx = 0; + for (unsigned i = 0; i != NumElts; ++i) + if (ShufMask.getOperand(i).getOpcode() != ISD::UNDEF) { + unsigned Idx=cast(ShufMask.getOperand(i))->getZExtValue(); + int V = (Idx < NumElts) ? 0 : 1; + if (VecNum == -1) { + VecNum = V; + BaseIdx = Idx; + } else { + if (BaseIdx != Idx) + isSplat = false; + if (VecNum != V) { + isUnary = false; + break; + } + } + } + + // Normalize unary shuffle so the RHS is undef. + if (isUnary && VecNum == 1) + std::swap(N0, N1); // If it is a splat, check if the argument vector is a build_vector with // all scalar elements the same. - if (cast(N)->isSplat()) { + if (isSplat) { SDNode *V = N0.getNode(); - // If this is a bit convert that changes the element type of the vector but // not the number of vector elements, look through it. Be careful not to @@ -5344,7 +5397,6 @@ if (V->getOpcode() == ISD::BUILD_VECTOR) { unsigned NumElems = V->getNumOperands(); - unsigned BaseIdx = cast(N)->getSplatIndex(); if (NumElems > BaseIdx) { SDValue Base; bool AllSame = true; @@ -5369,6 +5421,38 @@ } } } + + // If it is a unary or the LHS and the RHS are the same node, turn the RHS + // into an undef. + if (isUnary || N0 == N1) { + // Check the SHUFFLE mask, mapping any inputs from the 2nd operand into the + // first operand. + SmallVector MappedOps; + + for (unsigned i = 0; i != NumElts; ++i) { + if (ShufMask.getOperand(i).getOpcode() == ISD::UNDEF || + cast(ShufMask.getOperand(i))->getZExtValue() < + NumElts) { + MappedOps.push_back(ShufMask.getOperand(i)); + } else { + unsigned NewIdx = + cast(ShufMask.getOperand(i))->getZExtValue() - + NumElts; + MappedOps.push_back(DAG.getConstant(NewIdx, + ShufMask.getOperand(i).getValueType())); + } + } + + ShufMask = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + ShufMask.getValueType(), + &MappedOps[0], MappedOps.size()); + AddToWorkList(ShufMask.getNode()); + return DAG.getNode(ISD::VECTOR_SHUFFLE, N->getDebugLoc(), + N->getValueType(0), N0, + DAG.getUNDEF(N->getValueType(0)), + ShufMask); + } + return SDValue(); } @@ -5377,42 +5461,52 @@ /// e.g. AND V, <0xffffffff, 0, 0xffffffff, 0>. ==> /// vector_shuffle V, Zero, <0, 4, 2, 4> SDValue DAGCombiner::XformToShuffleWithZero(SDNode *N) { - MVT VT = N->getValueType(0); - DebugLoc dl = N->getDebugLoc(); SDValue LHS = N->getOperand(0); SDValue RHS = N->getOperand(1); if (N->getOpcode() == ISD::AND) { if (RHS.getOpcode() == ISD::BIT_CONVERT) RHS = RHS.getOperand(0); if (RHS.getOpcode() == ISD::BUILD_VECTOR) { - SmallVector Indices; - unsigned NumElts = RHS.getNumOperands(); + std::vector IdxOps; + unsigned NumOps = RHS.getNumOperands(); + unsigned NumElts = NumOps; for (unsigned i = 0; i != NumElts; ++i) { SDValue Elt = RHS.getOperand(i); if (!isa(Elt)) return SDValue(); else if (cast(Elt)->isAllOnesValue()) - Indices.push_back(i); + IdxOps.push_back(DAG.getIntPtrConstant(i)); else if (cast(Elt)->isNullValue()) - Indices.push_back(NumElts); + IdxOps.push_back(DAG.getIntPtrConstant(NumElts)); else return SDValue(); } // Let's see if the target supports this vector_shuffle. - MVT RVT = RHS.getValueType(); - if (!TLI.isVectorClearMaskLegal(&Indices[0], RVT)) + if (!TLI.isVectorClearMaskLegal(IdxOps, TLI.getPointerTy(), DAG)) return SDValue(); // Return the new VECTOR_SHUFFLE node. - MVT EVT = RVT.getVectorElementType(); - SmallVector ZeroOps(RVT.getVectorNumElements(), - DAG.getConstant(0, EVT)); - SDValue Zero = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), - RVT, &ZeroOps[0], ZeroOps.size()); - LHS = DAG.getNode(ISD::BIT_CONVERT, dl, RVT, LHS); - SDValue Shuf = DAG.getVectorShuffle(RVT, dl, LHS, Zero, &Indices[0]); - return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Shuf); + MVT EVT = RHS.getValueType().getVectorElementType(); + MVT VT = MVT::getVectorVT(EVT, NumElts); + MVT MaskVT = MVT::getVectorVT(TLI.getPointerTy(), NumElts); + std::vector Ops; + LHS = DAG.getNode(ISD::BIT_CONVERT, LHS.getDebugLoc(), VT, LHS); + Ops.push_back(LHS); + AddToWorkList(LHS.getNode()); + std::vector ZeroOps(NumElts, DAG.getConstant(0, EVT)); + Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + VT, &ZeroOps[0], ZeroOps.size())); + Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + MaskVT, &IdxOps[0], IdxOps.size())); + SDValue Result = DAG.getNode(ISD::VECTOR_SHUFFLE, N->getDebugLoc(), + VT, &Ops[0], Ops.size()); + + if (VT != N->getValueType(0)) + Result = DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), + N->getValueType(0), Result); + + return Result; } } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Fri Apr 24 07:40:33 2009 @@ -267,10 +267,16 @@ bool isVolatile, SDValue ValOp, unsigned StWidth, DebugLoc dl); - /// promoteShuffle - Promote a shuffle mask of a vector VT to perform the - /// same shuffle on a vector of NVT. Must not create an illegal shuffle mask. - SDValue promoteShuffle(MVT NVT, MVT VT, DebugLoc dl, SDValue N1, SDValue N2, - const int *Mask) const; + /// isShuffleLegal - Return non-null if a vector shuffle is legal with the + /// specified mask and type. Targets can specify exactly which masks they + /// support and the code generator is tasked with not creating illegal masks. + /// + /// Note that this will also return true for shuffles that are promoted to a + /// different type. + /// + /// If this is a legal shuffle, this method returns the (possibly promoted) + /// build_vector Mask. If it's not a legal shuffle, it returns null. + SDNode *isShuffleLegal(MVT VT, SDValue Mask) const; bool LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest, SmallPtrSet &NodesLeadingTo); @@ -313,35 +319,50 @@ }; } -/// promoteShuffle - Promote a shuffle mask of a vector VT to perform the -/// same shuffle on a vector of NVT. Must not create an illegal shuffle mask. -/// e.g. <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3> -SDValue SelectionDAGLegalize::promoteShuffle(MVT NVT, MVT VT, DebugLoc dl, - SDValue N1, SDValue N2, - const int *Mask) const { - MVT EltVT = NVT.getVectorElementType(); - int NumMaskElts = VT.getVectorNumElements(); - int NumDestElts = NVT.getVectorNumElements(); - unsigned NumEltsGrowth = NumDestElts / NumMaskElts; - - assert(NumEltsGrowth && "Cannot promote to vector type with fewer elts!"); - - if (NumEltsGrowth == 1) - return DAG.getVectorShuffle(NVT, dl, N1, N2, Mask); - - SmallVector NewMask; - for (int i = 0; i != NumMaskElts; ++i) { - int Idx = Mask[i]; - for (unsigned j = 0; j != NumEltsGrowth; ++j) { - if (Idx < 0) - NewMask.push_back(-1); - else - NewMask.push_back(Idx * NumEltsGrowth + j); +/// isVectorShuffleLegal - Return true if a vector shuffle is legal with the +/// specified mask and type. Targets can specify exactly which masks they +/// support and the code generator is tasked with not creating illegal masks. +/// +/// Note that this will also return true for shuffles that are promoted to a +/// different type. +SDNode *SelectionDAGLegalize::isShuffleLegal(MVT VT, SDValue Mask) const { + switch (TLI.getOperationAction(ISD::VECTOR_SHUFFLE, VT)) { + default: return 0; + case TargetLowering::Legal: + case TargetLowering::Custom: + break; + case TargetLowering::Promote: { + // If this is promoted to a different type, convert the shuffle mask and + // ask if it is legal in the promoted type! + MVT NVT = TLI.getTypeToPromoteTo(ISD::VECTOR_SHUFFLE, VT); + MVT EltVT = NVT.getVectorElementType(); + + // If we changed # elements, change the shuffle mask. + unsigned NumEltsGrowth = + NVT.getVectorNumElements() / VT.getVectorNumElements(); + assert(NumEltsGrowth && "Cannot promote to vector type with fewer elts!"); + if (NumEltsGrowth > 1) { + // Renumber the elements. + SmallVector Ops; + for (unsigned i = 0, e = Mask.getNumOperands(); i != e; ++i) { + SDValue InOp = Mask.getOperand(i); + for (unsigned j = 0; j != NumEltsGrowth; ++j) { + if (InOp.getOpcode() == ISD::UNDEF) + Ops.push_back(DAG.getUNDEF(EltVT)); + else { + unsigned InEltNo = cast(InOp)->getZExtValue(); + Ops.push_back(DAG.getConstant(InEltNo*NumEltsGrowth+j, EltVT)); + } + } + } + Mask = DAG.getNode(ISD::BUILD_VECTOR, Mask.getDebugLoc(), + NVT, &Ops[0], Ops.size()); } + VT = NVT; + break; + } } - assert((int)NewMask.size() == NumDestElts && "Non-integer NumEltsGrowth?"); - assert(TLI.isShuffleMaskLegal(&Mask[0], NVT) && "Shuffle not legal?"); - return DAG.getVectorShuffle(NVT, dl, N1, N2, &NewMask[0]); + return TLI.isShuffleMaskLegal(Mask, VT) ? Mask.getNode() : 0; } SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag, @@ -1631,15 +1652,25 @@ Tmp1.getValueType(), Tmp2); unsigned NumElts = Tmp1.getValueType().getVectorNumElements(); + MVT ShufMaskVT = + MVT::getIntVectorWithNumElements(NumElts); + MVT ShufMaskEltVT = ShufMaskVT.getVectorElementType(); + // We generate a shuffle of InVec and ScVec, so the shuffle mask // should be 0,1,2,3,4,5... with the appropriate element replaced with // elt 0 of the RHS. - SmallVector ShufOps; - for (unsigned i = 0; i != NumElts; ++i) - ShufOps.push_back(i != InsertPos->getZExtValue() ? i : NumElts); - - Result = DAG.getVectorShuffle(Tmp1.getValueType(), dl, Tmp1, ScVec, - &ShufOps[0]); + SmallVector ShufOps; + for (unsigned i = 0; i != NumElts; ++i) { + if (i != InsertPos->getZExtValue()) + ShufOps.push_back(DAG.getConstant(i, ShufMaskEltVT)); + else + ShufOps.push_back(DAG.getConstant(NumElts, ShufMaskEltVT)); + } + SDValue ShufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, ShufMaskVT, + &ShufOps[0], ShufOps.size()); + + Result = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, Tmp1.getValueType(), + Tmp1, ScVec, ShufMask); Result = LegalizeOp(Result); break; } @@ -1677,14 +1708,13 @@ case ISD::VECTOR_SHUFFLE: Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the input vectors, Tmp2 = LegalizeOp(Node->getOperand(1)); // but not the shuffle mask. - Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); + Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2)); // Allow targets to custom lower the SHUFFLEs they support. switch (TLI.getOperationAction(ISD::VECTOR_SHUFFLE, Result.getValueType())){ default: assert(0 && "Unknown operation action!"); case TargetLowering::Legal: - assert(TLI.isShuffleMaskLegal(cast(Node)->getMask(), - Result.getValueType()) && + assert(isShuffleLegal(Result.getValueType(), Node->getOperand(2)) && "vector shuffle should not be created if not legal!"); break; case TargetLowering::Custom: @@ -1698,21 +1728,23 @@ MVT VT = Node->getValueType(0); MVT EltVT = VT.getVectorElementType(); MVT PtrVT = TLI.getPointerTy(); - const int *Mask = cast(Node)->getMask(); - int NumElems = VT.getVectorNumElements(); + SDValue Mask = Node->getOperand(2); + unsigned NumElems = Mask.getNumOperands(); SmallVector Ops; - for (int i = 0; i != NumElems; ++i) { - if (Mask[i] < 0) { + for (unsigned i = 0; i != NumElems; ++i) { + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) { Ops.push_back(DAG.getUNDEF(EltVT)); - continue; + } else { + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + unsigned Idx = cast(Arg)->getZExtValue(); + if (Idx < NumElems) + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Tmp1, + DAG.getConstant(Idx, PtrVT))); + else + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Tmp2, + DAG.getConstant(Idx - NumElems, PtrVT))); } - int Idx = Mask[i]; - if (Idx < NumElems) - Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Tmp1, - DAG.getConstant(Idx, PtrVT))); - else - Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Tmp2, - DAG.getConstant(Idx - NumElems, PtrVT))); } Result = DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], Ops.size()); break; @@ -1727,8 +1759,9 @@ Tmp2 = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Tmp2); // Convert the shuffle mask to the right # elements. - Result = promoteShuffle(NVT, OVT, dl, Tmp1, Tmp2, - cast(Node)->getMask()); + Tmp3 = SDValue(isShuffleLegal(OVT, Node->getOperand(2)), 0); + assert(Tmp3.getNode() && "Shuffle not legal?"); + Result = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, NVT, Tmp1, Tmp2, Tmp3); Result = DAG.getNode(ISD::BIT_CONVERT, dl, OVT, Result); break; } @@ -5457,7 +5490,6 @@ // FIXME: it would be far nicer to change this into map // and use a bitmask instead of a list of elements. - // FIXME: this doesn't treat <0, u, 0, u> for example, as a splat. std::map > Values; Values[SplatValue].push_back(0); bool isConstant = true; @@ -5514,17 +5546,21 @@ if (SplatValue.getNode()) { // Splat of one value? // Build the shuffle constant vector: <0, 0, 0, 0> - SmallVector ZeroVec(NumElems, 0); + MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); + SDValue Zero = DAG.getConstant(0, MaskVT.getVectorElementType()); + std::vector ZeroVec(NumElems, Zero); + SDValue SplatMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &ZeroVec[0], ZeroVec.size()); // If the target supports VECTOR_SHUFFLE and this shuffle mask, use it. - if (TLI.isShuffleMaskLegal(&ZeroVec[0], Node->getValueType(0))) { + if (isShuffleLegal(VT, SplatMask)) { // Get the splatted value into the low element of a vector register. SDValue LowValVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, SplatValue); // Return shuffle(LowValVec, undef, <0,0,0,0>) - return DAG.getVectorShuffle(VT, dl, LowValVec, DAG.getUNDEF(VT), - &ZeroVec[0]); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, LowValVec, + DAG.getUNDEF(VT), SplatMask); } } @@ -5546,25 +5582,35 @@ std::swap(Val1, Val2); // Build the shuffle constant vector: e.g. <0, 4, 0, 4> - SmallVector ShuffleMask(NumElems, -1); + MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); + MVT MaskEltVT = MaskVT.getVectorElementType(); + std::vector MaskVec(NumElems); // Set elements of the shuffle mask for Val1. std::vector &Val1Elts = Values[Val1]; for (unsigned i = 0, e = Val1Elts.size(); i != e; ++i) - ShuffleMask[Val1Elts[i]] = 0; + MaskVec[Val1Elts[i]] = DAG.getConstant(0, MaskEltVT); // Set elements of the shuffle mask for Val2. std::vector &Val2Elts = Values[Val2]; for (unsigned i = 0, e = Val2Elts.size(); i != e; ++i) if (Val2.getOpcode() != ISD::UNDEF) - ShuffleMask[Val2Elts[i]] = NumElems; + MaskVec[Val2Elts[i]] = DAG.getConstant(NumElems, MaskEltVT); + else + MaskVec[Val2Elts[i]] = DAG.getUNDEF(MaskEltVT); + + SDValue ShuffleMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskVec[0], MaskVec.size()); // If the target supports SCALAR_TO_VECTOR and this shuffle mask, use it. if (TLI.isOperationLegalOrCustom(ISD::SCALAR_TO_VECTOR, VT) && - TLI.isShuffleMaskLegal(&ShuffleMask[0], VT)) { + isShuffleLegal(VT, ShuffleMask)) { Val1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Val1); Val2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Val2); - return DAG.getVectorShuffle(VT, dl, Val1, Val2, &ShuffleMask[0]); + SDValue Ops[] = { Val1, Val2, ShuffleMask }; + + // Return shuffle(LoValVec, HiValVec, <0,1,0,1>) + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, Ops, 3); } } @@ -8020,19 +8066,36 @@ case ISD::VECTOR_SHUFFLE: { SDValue Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT); SDValue Tmp2 = WidenVectorOp(Node->getOperand(1), WidenVT); - const int *Mask = cast(Node)->getMask(); - SmallVector NewMask; + // VECTOR_SHUFFLE 3rd operand must be a constant build vector that is + // used as permutation array. We build the vector here instead of widening + // because we don't want to legalize and have it turned to something else. + SDValue PermOp = Node->getOperand(2); + SDValueVector NewOps; + MVT PVT = PermOp.getValueType().getVectorElementType(); for (unsigned i = 0; i < NumElts; ++i) { - int Idx = Mask[i]; - if (Idx < (int)NumElts) - NewMask.push_back(Idx); - else - NewMask.push_back(Idx + NewNumElts - NumElts); + if (PermOp.getOperand(i).getOpcode() == ISD::UNDEF) { + NewOps.push_back(PermOp.getOperand(i)); + } else { + unsigned Idx = + cast(PermOp.getOperand(i))->getZExtValue(); + if (Idx < NumElts) { + NewOps.push_back(PermOp.getOperand(i)); + } + else { + NewOps.push_back(DAG.getConstant(Idx + NewNumElts - NumElts, + PermOp.getOperand(i).getValueType())); + } + } } - for (unsigned i = NumElts; i < NewNumElts; ++i) - NewMask.push_back(-1); - - Result = DAG.getVectorShuffle(WidenVT, dl, Tmp1, Tmp2, &NewMask[0]); + for (unsigned i = NumElts; i < NewNumElts; ++i) { + NewOps.push_back(DAG.getUNDEF(PVT)); + } + + SDValue Tmp3 = DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::getVectorVT(PVT, NewOps.size()), + &NewOps[0], NewOps.size()); + + Result = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, WidenVT, Tmp1, Tmp2, Tmp3); break; } case ISD::LOAD: { Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Fri Apr 24 07:40:33 2009 @@ -772,8 +772,10 @@ // If Lo or Hi uses elements from at most two of the four input vectors, then // express it as a vector shuffle of those two inputs. Otherwise extract the // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR. - const int *Mask = cast(N)->getMask(); - SmallVector Ops; + SDValue Mask = N->getOperand(2); + MVT IdxVT = Mask.getValueType().getVectorElementType(); + SmallVector Ops; + Ops.reserve(NewElts); for (unsigned High = 0; High < 2; ++High) { SDValue &Output = High ? Hi : Lo; @@ -785,15 +787,18 @@ unsigned FirstMaskIdx = High * NewElts; bool useBuildVector = false; for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { + SDValue Arg = Mask.getOperand(FirstMaskIdx + MaskOffset); + // The mask element. This indexes into the input. - int Idx = Mask[FirstMaskIdx + MaskOffset]; + unsigned Idx = Arg.getOpcode() == ISD::UNDEF ? + -1U : cast(Arg)->getZExtValue(); // The input vector this mask element indexes into. - unsigned Input = (unsigned)Idx / NewElts; + unsigned Input = Idx / NewElts; if (Input >= array_lengthof(Inputs)) { // The mask element does not index into any input vector. - Ops.push_back(-1); + Ops.push_back(DAG.getUNDEF(IdxVT)); continue; } @@ -821,24 +826,27 @@ } // Add the mask index for the new shuffle vector. - Ops.push_back(Idx + OpNo * NewElts); + Ops.push_back(DAG.getConstant(Idx + OpNo * NewElts, IdxVT)); } if (useBuildVector) { MVT EltVT = NewVT.getVectorElementType(); - SmallVector SVOps; + Ops.clear(); // Extract the input elements by hand. for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { + SDValue Arg = Mask.getOperand(FirstMaskIdx + MaskOffset); + // The mask element. This indexes into the input. - int Idx = Mask[FirstMaskIdx + MaskOffset]; + unsigned Idx = Arg.getOpcode() == ISD::UNDEF ? + -1U : cast(Arg)->getZExtValue(); // The input vector this mask element indexes into. - unsigned Input = (unsigned)Idx / NewElts; + unsigned Input = Idx / NewElts; if (Input >= array_lengthof(Inputs)) { // The mask element is "undef" or indexes off the end of the input. - SVOps.push_back(DAG.getUNDEF(EltVT)); + Ops.push_back(DAG.getUNDEF(EltVT)); continue; } @@ -846,22 +854,25 @@ Idx -= Input * NewElts; // Extract the vector element by hand. - SVOps.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, - Inputs[Input], DAG.getIntPtrConstant(Idx))); + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, + Inputs[Input], DAG.getIntPtrConstant(Idx))); } // Construct the Lo/Hi output using a BUILD_VECTOR. - Output = DAG.getNode(ISD::BUILD_VECTOR,dl,NewVT, &SVOps[0], SVOps.size()); + Output = DAG.getNode(ISD::BUILD_VECTOR, dl, NewVT, &Ops[0], Ops.size()); } else if (InputUsed[0] == -1U) { // No input vectors were used! The result is undefined. Output = DAG.getUNDEF(NewVT); } else { + // At least one input vector was used. Create a new shuffle vector. + SDValue NewMask = DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::getVectorVT(IdxVT, Ops.size()), + &Ops[0], Ops.size()); SDValue Op0 = Inputs[InputUsed[0]]; // If only one input was used, use an undefined vector for the other. SDValue Op1 = InputUsed[1] == -1U ? DAG.getUNDEF(NewVT) : Inputs[InputUsed[1]]; - // At least one input vector was used. Create a new shuffle vector. - Output = DAG.getVectorShuffle(NewVT, dl, Op0, Op1, &Ops[0]); + Output = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, NewVT, Op0, Op1, NewMask); } Ops.clear(); @@ -1462,15 +1473,18 @@ if (NumOperands == 2) { // Replace concat of two operands with a shuffle. - SmallVector MaskOps(WidenNumElts); + MVT PtrVT = TLI.getPointerTy(); + SmallVector MaskOps(WidenNumElts); for (unsigned i=0; i < WidenNumElts/2; ++i) { - MaskOps[i] = i; - MaskOps[i+WidenNumElts/2] = i+WidenNumElts; + MaskOps[i] = DAG.getConstant(i, PtrVT); + MaskOps[i+WidenNumElts/2] = DAG.getConstant(i+WidenNumElts, PtrVT); } - return DAG.getVectorShuffle(WidenVT, dl, - GetWidenedVector(N->getOperand(0)), - GetWidenedVector(N->getOperand(1)), - &MaskOps[0]); + SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::getVectorVT(PtrVT, WidenNumElts), + &MaskOps[0], WidenNumElts); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, WidenVT, + GetWidenedVector(N->getOperand(0)), + GetWidenedVector(N->getOperand(1)), Mask); } } } @@ -1748,7 +1762,7 @@ SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(SDNode *N) { MVT VT = N->getValueType(0); - int NumElts = VT.getVectorNumElements(); + unsigned NumElts = VT.getVectorNumElements(); DebugLoc dl = N->getDebugLoc(); MVT WidenVT = TLI.getTypeToTransformTo(VT); @@ -1758,17 +1772,28 @@ SDValue InOp2 = GetWidenedVector(N->getOperand(1)); // Adjust mask based on new input vector length. - const int *Mask = cast(N)->getMask(); - SmallVector NewMask; - for (int i = 0; i < NumElts; ++i) { - if (Mask[i] < NumElts) - NewMask.push_back(Mask[i]); - else - NewMask.push_back(Mask[i] - NumElts + WidenNumElts); + SDValue Mask = N->getOperand(2); + SmallVector MaskOps(WidenNumElts); + MVT IdxVT = Mask.getValueType().getVectorElementType(); + for (unsigned i = 0; i < NumElts; ++i) { + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) + MaskOps[i] = Arg; + else { + unsigned Idx = cast(Arg)->getZExtValue(); + if (Idx < NumElts) + MaskOps[i] = Arg; + else + MaskOps[i] = DAG.getConstant(Idx - NumElts + WidenNumElts, IdxVT); + } } for (unsigned i = NumElts; i < WidenNumElts; ++i) - NewMask.push_back(-1); - return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, &NewMask[0]); + MaskOps[i] = DAG.getUNDEF(IdxVT); + SDValue NewMask = DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::getVectorVT(IdxVT, WidenNumElts), + &MaskOps[0], WidenNumElts); + + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, WidenVT, InOp1, InOp2, NewMask); } SDValue DAGTypeLegalizer::WidenVecRes_VSETCC(SDNode *N) { Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Fri Apr 24 07:40:33 2009 @@ -456,13 +456,6 @@ ID.AddInteger(AT->getRawSubclassData()); break; } - case ISD::VECTOR_SHUFFLE: { - const int *Mask = cast(N)->getMask(); - for (unsigned i = 0, e = N->getValueType(0).getVectorNumElements(); - i != e; ++i) - ID.AddInteger(Mask[i]); - break; - } } // end switch (N->getOpcode()) } @@ -769,6 +762,12 @@ assert(N->getValueType(0).isVector() && "Wrong return type!"); assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() && "Wrong number of operands!"); + MVT EltVT = N->getValueType(0).getVectorElementType(); + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) + assert((I->getValueType() == EltVT || + (EltVT.isInteger() && I->getValueType().isInteger() && + EltVT.bitsLE(I->getValueType()))) && + "Wrong operand type!"); break; } } @@ -1127,110 +1126,6 @@ return SDValue(CondCodeNodes[Cond], 0); } -static void commuteShuffle(SDValue &N1, SDValue &N2, SmallVectorImpl &M) { - std::swap(N1, N2); - int NElts = M.size(); - for (int i = 0; i != NElts; ++i) { - if (M[i] >= NElts) - M[i] -= NElts; - else if (M[i] >= 0) - M[i] += NElts; - } -} - -SDValue SelectionDAG::getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, - SDValue N2, const int *Mask) { - assert(N1.getValueType() == N2.getValueType() && "Invalid VECTOR_SHUFFLE"); - assert(VT.isVector() && N1.getValueType().isVector() && - "Vector Shuffle VTs must be a vectors"); - assert(VT.getVectorElementType() == N1.getValueType().getVectorElementType() - && "Vector Shuffle VTs must have same element type"); - - // Canonicalize shuffle undef, undef -> undef - if (N1.getOpcode() == ISD::UNDEF && N2.getOpcode() == ISD::UNDEF) - return N1; - - // Validate that all the indices past in in Mask are within the range of - // elements input to the shuffle. - int NElts = VT.getVectorNumElements(); - SmallVector MaskVec; - for (int i = 0; i != NElts; ++i) { - if (Mask[i] >= (NElts * 2)) { - assert(0 && "Index out of range"); - return SDValue(); - } - MaskVec.push_back(Mask[i]); - } - - // Canonicalize shuffle v, v -> v, undef - if (N1 == N2) { - N2 = getUNDEF(VT); - for (int i = 0; i != NElts; ++i) - if (MaskVec[i] >= NElts) MaskVec[i] -= NElts; - } - - // Canonicalize shuffle undef, v -> v, undef. Commute the shuffle mask. - if (N1.getOpcode() == ISD::UNDEF) - commuteShuffle(N1, N2, MaskVec); - - // Canonicalize all index into lhs, -> shuffle lhs, undef - // Canonicalize all index into rhs, -> shuffle rhs, undef - bool AllLHS = true, AllRHS = true; - bool N2Undef = N2.getOpcode() == ISD::UNDEF; - for (int i = 0; i != NElts; ++i) { - if (MaskVec[i] >= NElts) { - if (N2Undef) - MaskVec[i] = -1; - else - AllLHS = false; - } else if (MaskVec[i] >= 0) { - AllRHS = false; - } - } - if (AllLHS && AllRHS) - return getUNDEF(VT); - if (AllLHS) - N2 = getUNDEF(VT); - if (AllRHS) { - N1 = getUNDEF(VT); - commuteShuffle(N1, N2, MaskVec); - } - - // If Identity shuffle, or all shuffle in to undef, return that node. - bool AllUndef = true; - bool Identity = true; - for (int i = 0; i < NElts; ++i) { - if (MaskVec[i] >= 0 && MaskVec[i] != i) Identity = false; - if (MaskVec[i] >= 0) AllUndef = false; - } - if (Identity) - return N1; - if (AllUndef) - return getUNDEF(VT); - - FoldingSetNodeID ID; - SDValue Ops[2] = { N1, N2 }; - AddNodeIDNode(ID, ISD::VECTOR_SHUFFLE, getVTList(VT), Ops, 2); - for (int i = 0; i != NElts; ++i) - ID.AddInteger(MaskVec[i]); - - void* IP = 0; - 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 - // the node is deallocated, but recovered when the NodeAllocator is released. - int *MaskAlloc = OperandAllocator.Allocate(NElts); - memcpy(MaskAlloc, &MaskVec[0], NElts * sizeof(int)); - - ShuffleVectorSDNode *N = NodeAllocator.Allocate(); - new (N) ShuffleVectorSDNode(VT, dl, N1, N2, MaskAlloc); - CSEMap.InsertNode(N, IP); - AllNodes.push_back(N); - return SDValue(N, 0); -} - SDValue SelectionDAG::getConvertRndSat(MVT VT, DebugLoc dl, SDValue Val, SDValue DTy, SDValue STy, SDValue Rnd, SDValue Sat, @@ -2192,18 +2087,19 @@ SDValue SelectionDAG::getShuffleScalarElt(const SDNode *N, unsigned i) { MVT VT = N->getValueType(0); DebugLoc dl = N->getDebugLoc(); - const int *PermMask = cast(N)->getMask(); - if (PermMask[i] < 0) + SDValue PermMask = N->getOperand(2); + SDValue Idx = PermMask.getOperand(i); + if (Idx.getOpcode() == ISD::UNDEF) return getUNDEF(VT.getVectorElementType()); - int Index = PermMask[i]; - int NumElems = VT.getVectorNumElements(); + unsigned Index = cast(Idx)->getZExtValue(); + unsigned NumElems = PermMask.getNumOperands(); SDValue V = (Index < NumElems) ? N->getOperand(0) : N->getOperand(1); Index %= NumElems; if (V.getOpcode() == ISD::BIT_CONVERT) { V = V.getOperand(0); MVT VVT = V.getValueType(); - if (!VVT.isVector() || VVT.getVectorNumElements() != (unsigned)NumElems) + if (!VVT.isVector() || VVT.getVectorNumElements() != NumElems) return SDValue(); } if (V.getOpcode() == ISD::SCALAR_TO_VECTOR) @@ -2897,7 +2793,12 @@ } break; case ISD::VECTOR_SHUFFLE: - assert(0 && "should use getVectorShuffle constructor!"); + assert(N1.getValueType() == N2.getValueType() && + N1.getValueType().isVector() && + VT.isVector() && N3.getValueType().isVector() && + N3.getOpcode() == ISD::BUILD_VECTOR && + VT.getVectorNumElements() == N3.getNumOperands() && + "Illegal VECTOR_SHUFFLE node!"); break; case ISD::BIT_CONVERT: // Fold bit_convert nodes from a type to themselves. @@ -5421,14 +5322,14 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { if (!isTargetOpcode() && getOpcode() == ISD::VECTOR_SHUFFLE) { - const int *Mask = cast(this)->getMask(); + SDNode *Mask = getOperand(2).getNode(); OS << "<"; - for (unsigned i = 0, e = ValueList[0].getVectorNumElements(); i != e; ++i) { + for (unsigned i = 0, e = Mask->getNumOperands(); i != e; ++i) { if (i) OS << ","; - if (Mask[i] < 0) + if (Mask->getOperand(i).getOpcode() == ISD::UNDEF) OS << "u"; else - OS << Mask[i]; + OS << cast(Mask->getOperand(i))->getZExtValue(); } OS << ">"; } @@ -5709,13 +5610,3 @@ SplatBitSize = sz; return true; } - -bool ShuffleVectorSDNode::isSplatMask(const int *Mask, MVT VT) { - int Idx = -1; - for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { - if (Idx < 0) Idx = Mask[i]; - if (Mask[i] >= 0 && Mask[i] != Idx) - return false; - } - return true; -} Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Fri Apr 24 07:40:33 2009 @@ -870,7 +870,8 @@ if (ConstantFP *CFP = dyn_cast(C)) return N = DAG.getConstantFP(*CFP, VT); - if (isa(C) && !V->getType()->isAggregateType()) + if (isa(C) && !isa(V->getType()) && + !V->getType()->isAggregateType()) return N = DAG.getUNDEF(VT); if (ConstantExpr *CE = dyn_cast(C)) { @@ -924,11 +925,14 @@ for (unsigned i = 0; i != NumElements; ++i) Ops.push_back(getValue(CP->getOperand(i))); } else { - assert(isa(C) && "Unknown vector constant!"); + assert((isa(C) || isa(C)) && + "Unknown vector constant!"); MVT EltVT = TLI.getValueType(VecTy->getElementType()); SDValue Op; - if (EltVT.isFloatingPoint()) + if (isa(C)) + Op = DAG.getUNDEF(EltVT); + else if (EltVT.isFloatingPoint()) Op = DAG.getConstantFP(0, EltVT); else Op = DAG.getConstant(0, EltVT); @@ -2431,42 +2435,37 @@ // Utility for visitShuffleVector - Returns true if the mask is mask starting // from SIndx and increasing to the element length (undefs are allowed). -static bool SequentialMask(SmallVectorImpl &Mask, int SIndx) { - int MaskNumElts = Mask.size(); - for (int i = 0; i != MaskNumElts; ++i) - if ((Mask[i] >= 0) && (Mask[i] != i + SIndx)) - return false; +static bool SequentialMask(SDValue Mask, unsigned SIndx) { + unsigned MaskNumElts = Mask.getNumOperands(); + for (unsigned i = 0; i != MaskNumElts; ++i) { + if (Mask.getOperand(i).getOpcode() != ISD::UNDEF) { + unsigned Idx = cast(Mask.getOperand(i))->getZExtValue(); + if (Idx != i + SIndx) + return false; + } + } return true; } void SelectionDAGLowering::visitShuffleVector(User &I) { - SmallVector Mask; SDValue Src1 = getValue(I.getOperand(0)); SDValue Src2 = getValue(I.getOperand(1)); + SDValue Mask = getValue(I.getOperand(2)); - // Convert the ConstantVector mask operand into an array of ints, with -1 - // representing undef values. - SmallVector MaskElts; - cast(I.getOperand(2))->getVectorElements(MaskElts); - int MaskNumElts = MaskElts.size(); - for (int i = 0; i != MaskNumElts; ++i) { - if (isa(MaskElts[i])) - Mask.push_back(-1); - else - Mask.push_back(cast(MaskElts[i])->getSExtValue()); - } - MVT VT = TLI.getValueType(I.getType()); MVT SrcVT = Src1.getValueType(); + int MaskNumElts = Mask.getNumOperands(); int SrcNumElts = SrcVT.getVectorNumElements(); if (SrcNumElts == MaskNumElts) { - setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, - &Mask[0])); + setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, getCurDebugLoc(), + VT, Src1, Src2, Mask)); return; } // Normalize the shuffle vector since mask and vector length don't match. + MVT MaskEltVT = Mask.getValueType().getVectorElementType(); + if (SrcNumElts < MaskNumElts && MaskNumElts % SrcNumElts == 0) { // Mask is longer than the source vectors and is a multiple of the source // vectors. We can use concatenate vector to make the mask and vectors @@ -2480,33 +2479,44 @@ // Pad both vectors with undefs to make them the same length as the mask. unsigned NumConcat = MaskNumElts / SrcNumElts; - bool Src1U = Src1.getOpcode() == ISD::UNDEF; - bool Src2U = Src2.getOpcode() == ISD::UNDEF; SDValue UndefVal = DAG.getUNDEF(SrcVT); - SmallVector MOps1(NumConcat, UndefVal); - SmallVector MOps2(NumConcat, UndefVal); + SDValue* MOps1 = new SDValue[NumConcat]; + SDValue* MOps2 = new SDValue[NumConcat]; MOps1[0] = Src1; MOps2[0] = Src2; - - Src1 = Src1U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS, - getCurDebugLoc(), VT, - &MOps1[0], NumConcat); - Src2 = Src2U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS, - getCurDebugLoc(), VT, - &MOps2[0], NumConcat); + for (unsigned i = 1; i != NumConcat; ++i) { + MOps1[i] = UndefVal; + MOps2[i] = UndefVal; + } + Src1 = DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(), + VT, MOps1, NumConcat); + Src2 = DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(), + VT, MOps2, NumConcat); + + delete [] MOps1; + delete [] MOps2; // Readjust mask for new input vector length. - SmallVector MappedOps; + SmallVector MappedOps; for (int i = 0; i != MaskNumElts; ++i) { - int Idx = Mask[i]; - if (Idx < SrcNumElts) - MappedOps.push_back(Idx); - else - MappedOps.push_back(Idx + MaskNumElts - SrcNumElts); + if (Mask.getOperand(i).getOpcode() == ISD::UNDEF) { + MappedOps.push_back(Mask.getOperand(i)); + } else { + int Idx = cast(Mask.getOperand(i))->getZExtValue(); + if (Idx < SrcNumElts) + MappedOps.push_back(DAG.getConstant(Idx, MaskEltVT)); + else + MappedOps.push_back(DAG.getConstant(Idx + MaskNumElts - SrcNumElts, + MaskEltVT)); + } } - setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, - &MappedOps[0])); + Mask = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), + Mask.getValueType(), + &MappedOps[0], MappedOps.size()); + + setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, getCurDebugLoc(), + VT, Src1, Src2, Mask)); return; } @@ -2531,19 +2541,20 @@ int MaxRange[2] = {-1, -1}; for (int i = 0; i != MaskNumElts; ++i) { - int Idx = Mask[i]; - int Input = 0; - if (Idx < 0) - continue; - - if (Idx >= SrcNumElts) { - Input = 1; - Idx -= SrcNumElts; - } - if (Idx > MaxRange[Input]) - MaxRange[Input] = Idx; - if (Idx < MinRange[Input]) - MinRange[Input] = Idx; + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() != ISD::UNDEF) { + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + int Idx = cast(Arg)->getZExtValue(); + int Input = 0; + if (Idx >= SrcNumElts) { + Input = 1; + Idx -= SrcNumElts; + } + if (Idx > MaxRange[Input]) + MaxRange[Input] = Idx; + if (Idx < MinRange[Input]) + MinRange[Input] = Idx; + } } // Check if the access is smaller than the vector size and can we find @@ -2585,18 +2596,26 @@ } } // Calculate new mask. - SmallVector MappedOps; + SmallVector MappedOps; for (int i = 0; i != MaskNumElts; ++i) { - int Idx = Mask[i]; - if (Idx < 0) - MappedOps.push_back(Idx); - else if (Idx < SrcNumElts) - MappedOps.push_back(Idx - StartIdx[0]); - else - MappedOps.push_back(Idx - SrcNumElts - StartIdx[1] + MaskNumElts); + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) { + MappedOps.push_back(Arg); + } else { + int Idx = cast(Arg)->getZExtValue(); + if (Idx < SrcNumElts) + MappedOps.push_back(DAG.getConstant(Idx - StartIdx[0], MaskEltVT)); + else { + Idx = Idx - SrcNumElts - StartIdx[1] + MaskNumElts; + MappedOps.push_back(DAG.getConstant(Idx, MaskEltVT)); + } + } } - setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, - &MappedOps[0])); + Mask = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), + Mask.getValueType(), + &MappedOps[0], MappedOps.size()); + setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, getCurDebugLoc(), + VT, Src1, Src2, Mask)); return; } } @@ -2608,10 +2627,12 @@ MVT PtrVT = TLI.getPointerTy(); SmallVector Ops; for (int i = 0; i != MaskNumElts; ++i) { - if (Mask[i] < 0) { + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) { Ops.push_back(DAG.getUNDEF(EltVT)); } else { - int Idx = Mask[i]; + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + int Idx = cast(Arg)->getZExtValue(); if (Idx < SrcNumElts) Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), EltVT, Src1, DAG.getConstant(Idx, PtrVT))); Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp (original) +++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp Fri Apr 24 07:40:33 2009 @@ -1672,7 +1672,7 @@ static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { SDValue V1 = Op.getOperand(0); SDValue V2 = Op.getOperand(1); - const int *PermMask = cast(Op)->getMask(); + SDValue PermMask = Op.getOperand(2); DebugLoc dl = Op.getDebugLoc(); if (V2.getOpcode() == ISD::UNDEF) V2 = V1; @@ -1703,40 +1703,39 @@ } else assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE"); - for (unsigned i = 0; i != MaxElts; ++i) { - if (PermMask[i] < 0) - continue; - - unsigned SrcElt = PermMask[i]; - - if (monotonic) { - if (SrcElt >= V2EltIdx0) { - if (1 >= (++EltsFromV2)) { - V2Elt = (V2EltIdx0 - SrcElt) << 2; + for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) { + if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) { + unsigned SrcElt = cast (PermMask.getOperand(i))->getZExtValue(); + + if (monotonic) { + if (SrcElt >= V2EltIdx0) { + if (1 >= (++EltsFromV2)) { + V2Elt = (V2EltIdx0 - SrcElt) << 2; + } + } else if (CurrElt != SrcElt) { + monotonic = false; } - } else if (CurrElt != SrcElt) { - monotonic = false; - } - ++CurrElt; - } + ++CurrElt; + } - if (rotate) { - if (PrevElt > 0 && SrcElt < MaxElts) { - if ((PrevElt == SrcElt - 1) - || (PrevElt == MaxElts - 1 && SrcElt == 0)) { + if (rotate) { + if (PrevElt > 0 && SrcElt < MaxElts) { + if ((PrevElt == SrcElt - 1) + || (PrevElt == MaxElts - 1 && SrcElt == 0)) { + PrevElt = SrcElt; + if (SrcElt == 0) + V0Elt = i; + } else { + rotate = false; + } + } else if (PrevElt == 0) { + // First time through, need to keep track of previous element PrevElt = SrcElt; - if (SrcElt == 0) - V0Elt = i; } else { + // This isn't a rotation, takes elements from vector 2 rotate = false; } - } else if (PrevElt == 0) { - // First time through, need to keep track of previous element - PrevElt = SrcElt; - } else { - // This isn't a rotation, takes elements from vector 2 - rotate = false; } } } @@ -1769,8 +1768,12 @@ unsigned BytesPerElement = EltVT.getSizeInBits()/8; SmallVector ResultMask; - for (unsigned i = 0, e = MaxElts; i != e; ++i) { - unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i]; + for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) { + unsigned SrcElt; + if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF) + SrcElt = 0; + else + SrcElt = cast(PermMask.getOperand(i))->getZExtValue(); for (unsigned j = 0; j < BytesPerElement; ++j) { ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j, Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Fri Apr 24 07:40:33 2009 @@ -456,22 +456,22 @@ /// isConstantOrUndef - Op is either an undef node or a ConstantSDNode. Return /// true if Op is undef or if it matches the specified value. -static bool isConstantOrUndef(int Op, int Val) { - return Op < 0 || Op == Val; +static bool isConstantOrUndef(SDValue Op, unsigned Val) { + return Op.getOpcode() == ISD::UNDEF || + cast(Op)->getZExtValue() == Val; } /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUHUM instruction. -bool PPC::isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { - const int *Mask = N->getMask(); +bool PPC::isVPKUHUMShuffleMask(SDNode *N, bool isUnary) { if (!isUnary) { for (unsigned i = 0; i != 16; ++i) - if (!isConstantOrUndef(Mask[i], i*2+1)) + if (!isConstantOrUndef(N->getOperand(i), i*2+1)) return false; } else { for (unsigned i = 0; i != 8; ++i) - if (!isConstantOrUndef(Mask[i], i*2+1) || - !isConstantOrUndef(Mask[i+8], i*2+1)) + if (!isConstantOrUndef(N->getOperand(i), i*2+1) || + !isConstantOrUndef(N->getOperand(i+8), i*2+1)) return false; } return true; @@ -479,19 +479,18 @@ /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUWUM instruction. -bool PPC::isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { - const int *Mask = N->getMask(); +bool PPC::isVPKUWUMShuffleMask(SDNode *N, bool isUnary) { if (!isUnary) { for (unsigned i = 0; i != 16; i += 2) - if (!isConstantOrUndef(Mask[i ], i*2+2) || - !isConstantOrUndef(Mask[i+1], i*2+3)) + if (!isConstantOrUndef(N->getOperand(i ), i*2+2) || + !isConstantOrUndef(N->getOperand(i+1), i*2+3)) return false; } else { for (unsigned i = 0; i != 8; i += 2) - if (!isConstantOrUndef(Mask[i ], i*2+2) || - !isConstantOrUndef(Mask[i+1], i*2+3) || - !isConstantOrUndef(Mask[i+8], i*2+2) || - !isConstantOrUndef(Mask[i+9], i*2+3)) + if (!isConstantOrUndef(N->getOperand(i ), i*2+2) || + !isConstantOrUndef(N->getOperand(i+1), i*2+3) || + !isConstantOrUndef(N->getOperand(i+8), i*2+2) || + !isConstantOrUndef(N->getOperand(i+9), i*2+3)) return false; } return true; @@ -499,29 +498,27 @@ /// isVMerge - Common function, used to match vmrg* shuffles. /// -static bool isVMerge(ShuffleVectorSDNode *N, unsigned UnitSize, +static bool isVMerge(SDNode *N, unsigned UnitSize, unsigned LHSStart, unsigned RHSStart) { - assert(N->getValueType(0) == MVT::v16i8 && - "PPC only supports shuffles by bytes!"); + assert(N->getOpcode() == ISD::BUILD_VECTOR && + N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && "Unsupported merge size!"); - const int *Mask = N->getMask(); for (unsigned i = 0; i != 8/UnitSize; ++i) // Step over units for (unsigned j = 0; j != UnitSize; ++j) { // Step over bytes within unit - if (!isConstantOrUndef(Mask[i*UnitSize*2+j], + if (!isConstantOrUndef(N->getOperand(i*UnitSize*2+j), LHSStart+j+i*UnitSize) || - !isConstantOrUndef(Mask[i*UnitSize*2+UnitSize+j], + !isConstantOrUndef(N->getOperand(i*UnitSize*2+UnitSize+j), RHSStart+j+i*UnitSize)) return false; } - return true; + return true; } /// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for /// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). -bool PPC::isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, - bool isUnary) { +bool PPC::isVMRGLShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary) { if (!isUnary) return isVMerge(N, UnitSize, 8, 24); return isVMerge(N, UnitSize, 8, 8); @@ -529,8 +526,7 @@ /// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). -bool PPC::isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, - bool isUnary) { +bool PPC::isVMRGHShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary) { if (!isUnary) return isVMerge(N, UnitSize, 0, 16); return isVMerge(N, UnitSize, 0, 0); @@ -540,92 +536,91 @@ /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// amount, otherwise return -1. int PPC::isVSLDOIShuffleMask(SDNode *N, bool isUnary) { - assert(N->getValueType(0) == MVT::v16i8 && - "PPC only supports shuffles by bytes!"); - - ShuffleVectorSDNode *SVOp = cast(N); - + assert(N->getOpcode() == ISD::BUILD_VECTOR && + N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); // Find the first non-undef value in the shuffle mask. - const int *Mask = SVOp->getMask(); unsigned i; - for (i = 0; i != 16 && Mask[i] < 0; ++i) + for (i = 0; i != 16 && N->getOperand(i).getOpcode() == ISD::UNDEF; ++i) /*search*/; if (i == 16) return -1; // all undef. - // Otherwise, check to see if the rest of the elements are consecutively + // Otherwise, check to see if the rest of the elements are consequtively // numbered from this value. - unsigned ShiftAmt = Mask[i]; + unsigned ShiftAmt = cast(N->getOperand(i))->getZExtValue(); if (ShiftAmt < i) return -1; ShiftAmt -= i; if (!isUnary) { - // Check the rest of the elements to see if they are consecutive. + // Check the rest of the elements to see if they are consequtive. for (++i; i != 16; ++i) - if (!isConstantOrUndef(Mask[i], ShiftAmt+i)) + if (!isConstantOrUndef(N->getOperand(i), ShiftAmt+i)) return -1; } else { - // Check the rest of the elements to see if they are consecutive. + // Check the rest of the elements to see if they are consequtive. for (++i; i != 16; ++i) - if (!isConstantOrUndef(Mask[i], (ShiftAmt+i) & 15)) + if (!isConstantOrUndef(N->getOperand(i), (ShiftAmt+i) & 15)) return -1; } + return ShiftAmt; } /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a splat of a single element that is suitable for input to /// VSPLTB/VSPLTH/VSPLTW. -bool PPC::isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize) { - assert(N->getValueType(0) == MVT::v16i8 && +bool PPC::isSplatShuffleMask(SDNode *N, unsigned EltSize) { + assert(N->getOpcode() == ISD::BUILD_VECTOR && + N->getNumOperands() == 16 && (EltSize == 1 || EltSize == 2 || EltSize == 4)); // This is a splat operation if each element of the permute is the same, and // if the value doesn't reference the second vector. - const int *Mask = N->getMask(); - unsigned ElementBase = Mask[0]; - - // FIXME: Handle UNDEF elements too! - if (ElementBase >= 16) + unsigned ElementBase = 0; + SDValue Elt = N->getOperand(0); + if (ConstantSDNode *EltV = dyn_cast(Elt)) + ElementBase = EltV->getZExtValue(); + else + return false; // FIXME: Handle UNDEF elements too! + + if (cast(Elt)->getZExtValue() >= 16) return false; - // Check that the indices are consecutive, in the case of a multi-byte element - // splatted with a v16i8 mask. - for (unsigned i = 1; i != EltSize; ++i) - if (Mask[i] < 0 || Mask[i] != (int)(i+ElementBase)) + // Check that they are consequtive. + for (unsigned i = 1; i != EltSize; ++i) { + if (!isa(N->getOperand(i)) || + cast(N->getOperand(i))->getZExtValue() != i+ElementBase) return false; + } + assert(isa(Elt) && "Invalid VECTOR_SHUFFLE mask!"); for (unsigned i = EltSize, e = 16; i != e; i += EltSize) { - if (Mask[i] < 0) continue; + if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; + assert(isa(N->getOperand(i)) && + "Invalid VECTOR_SHUFFLE mask!"); for (unsigned j = 0; j != EltSize; ++j) - if (Mask[i+j] != Mask[j]) + if (N->getOperand(i+j) != N->getOperand(j)) return false; } + return true; } /// isAllNegativeZeroVector - Returns true if all elements of build_vector /// are -0.0. bool PPC::isAllNegativeZeroVector(SDNode *N) { - BuildVectorSDNode *BV = cast(N); - - APInt APVal, APUndef; - unsigned BitSize; - bool HasAnyUndefs; - - if (BV->isConstantSplat(APVal, APUndef, BitSize, HasAnyUndefs, 32)) - if (ConstantFPSDNode *CFP = dyn_cast(N->getOperand(0))) + assert(N->getOpcode() == ISD::BUILD_VECTOR); + if (PPC::isSplatShuffleMask(N, N->getNumOperands())) + if (ConstantFPSDNode *CFP = dyn_cast(N)) return CFP->getValueAPF().isNegZero(); - return false; } /// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the /// specified isSplatShuffleMask VECTOR_SHUFFLE mask. unsigned PPC::getVSPLTImmediate(SDNode *N, unsigned EltSize) { - ShuffleVectorSDNode *SVOp = cast(N); - assert(isSplatShuffleMask(SVOp, EltSize)); - return SVOp->getMask()[0] / EltSize; + assert(isSplatShuffleMask(N, EltSize)); + return cast(N->getOperand(0))->getZExtValue() / EltSize; } /// get_VSPLTI_elt - If this is a build_vector of constants which can be formed @@ -3154,10 +3149,11 @@ LHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, LHS); RHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, RHS); - int Ops[16]; + SDValue Ops[16]; for (unsigned i = 0; i != 16; ++i) - Ops[i] = i + Amt; - SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, LHS, RHS, Ops); + Ops[i] = DAG.getConstant(i+Amt, MVT::i8); + SDValue T = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v16i8, LHS, RHS, + DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8, Ops,16)); return DAG.getNode(ISD::BIT_CONVERT, dl, VT, T); } @@ -3358,7 +3354,7 @@ OpLHS = GeneratePerfectShuffle(PerfectShuffleTable[LHSID], LHS, RHS, DAG, dl); OpRHS = GeneratePerfectShuffle(PerfectShuffleTable[RHSID], LHS, RHS, DAG, dl); - int ShufIdxs[16]; + unsigned ShufIdxs[16]; switch (OpNum) { default: assert(0 && "Unknown i32 permute!"); case OP_VMRGHW: @@ -3396,11 +3392,13 @@ case OP_VSLDOI12: return BuildVSLDOI(OpLHS, OpRHS, 12, OpLHS.getValueType(), DAG, dl); } - MVT VT = OpLHS.getValueType(); - OpLHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OpLHS); - OpRHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OpRHS); - SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, OpLHS, OpRHS, ShufIdxs); - return DAG.getNode(ISD::BIT_CONVERT, dl, VT, T); + SDValue Ops[16]; + for (unsigned i = 0; i != 16; ++i) + Ops[i] = DAG.getConstant(ShufIdxs[i], MVT::i8); + + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, OpLHS.getValueType(), + OpLHS, OpRHS, + DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8, Ops, 16)); } /// LowerVECTOR_SHUFFLE - Return the code we lower for VECTOR_SHUFFLE. If this @@ -3408,30 +3406,28 @@ /// return the code it can be lowered into. Worst case, it can always be /// lowered into a vperm. SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, - SelectionDAG &DAG) { + SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); SDValue V1 = Op.getOperand(0); SDValue V2 = Op.getOperand(1); - ShuffleVectorSDNode *SVOp = cast(Op); - const int *PermMask = SVOp->getMask(); - MVT VT = Op.getValueType(); + SDValue PermMask = Op.getOperand(2); // Cases that are handled by instructions that take permute immediates // (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be // selected by the instruction selector. if (V2.getOpcode() == ISD::UNDEF) { - if (PPC::isSplatShuffleMask(SVOp, 1) || - PPC::isSplatShuffleMask(SVOp, 2) || - PPC::isSplatShuffleMask(SVOp, 4) || - PPC::isVPKUWUMShuffleMask(SVOp, true) || - PPC::isVPKUHUMShuffleMask(SVOp, true) || - PPC::isVSLDOIShuffleMask(SVOp, true) != -1 || - PPC::isVMRGLShuffleMask(SVOp, 1, true) || - PPC::isVMRGLShuffleMask(SVOp, 2, true) || - PPC::isVMRGLShuffleMask(SVOp, 4, true) || - PPC::isVMRGHShuffleMask(SVOp, 1, true) || - PPC::isVMRGHShuffleMask(SVOp, 2, true) || - PPC::isVMRGHShuffleMask(SVOp, 4, true)) { + if (PPC::isSplatShuffleMask(PermMask.getNode(), 1) || + PPC::isSplatShuffleMask(PermMask.getNode(), 2) || + PPC::isSplatShuffleMask(PermMask.getNode(), 4) || + PPC::isVPKUWUMShuffleMask(PermMask.getNode(), true) || + PPC::isVPKUHUMShuffleMask(PermMask.getNode(), true) || + PPC::isVSLDOIShuffleMask(PermMask.getNode(), true) != -1 || + PPC::isVMRGLShuffleMask(PermMask.getNode(), 1, true) || + PPC::isVMRGLShuffleMask(PermMask.getNode(), 2, true) || + PPC::isVMRGLShuffleMask(PermMask.getNode(), 4, true) || + PPC::isVMRGHShuffleMask(PermMask.getNode(), 1, true) || + PPC::isVMRGHShuffleMask(PermMask.getNode(), 2, true) || + PPC::isVMRGHShuffleMask(PermMask.getNode(), 4, true)) { return Op; } } @@ -3439,15 +3435,15 @@ // Altivec has a variety of "shuffle immediates" that take two vector inputs // and produce a fixed permutation. If any of these match, do not lower to // VPERM. - if (PPC::isVPKUWUMShuffleMask(SVOp, false) || - PPC::isVPKUHUMShuffleMask(SVOp, false) || - PPC::isVSLDOIShuffleMask(SVOp, false) != -1 || - PPC::isVMRGLShuffleMask(SVOp, 1, false) || - PPC::isVMRGLShuffleMask(SVOp, 2, false) || - PPC::isVMRGLShuffleMask(SVOp, 4, false) || - PPC::isVMRGHShuffleMask(SVOp, 1, false) || - PPC::isVMRGHShuffleMask(SVOp, 2, false) || - PPC::isVMRGHShuffleMask(SVOp, 4, false)) + if (PPC::isVPKUWUMShuffleMask(PermMask.getNode(), false) || + PPC::isVPKUHUMShuffleMask(PermMask.getNode(), false) || + PPC::isVSLDOIShuffleMask(PermMask.getNode(), false) != -1 || + PPC::isVMRGLShuffleMask(PermMask.getNode(), 1, false) || + PPC::isVMRGLShuffleMask(PermMask.getNode(), 2, false) || + PPC::isVMRGLShuffleMask(PermMask.getNode(), 4, false) || + PPC::isVMRGHShuffleMask(PermMask.getNode(), 1, false) || + PPC::isVMRGHShuffleMask(PermMask.getNode(), 2, false) || + PPC::isVMRGHShuffleMask(PermMask.getNode(), 4, false)) return Op; // Check to see if this is a shuffle of 4-byte values. If so, we can use our @@ -3457,10 +3453,11 @@ for (unsigned i = 0; i != 4 && isFourElementShuffle; ++i) { // Element number unsigned EltNo = 8; // Start out undef. for (unsigned j = 0; j != 4; ++j) { // Intra-element byte. - if (PermMask[i*4+j] < 0) + if (PermMask.getOperand(i*4+j).getOpcode() == ISD::UNDEF) continue; // Undef, ignore it. - unsigned ByteSource = PermMask[i*4+j]; + unsigned ByteSource = + cast(PermMask.getOperand(i*4+j))->getZExtValue(); if ((ByteSource & 3) != j) { isFourElementShuffle = false; break; @@ -3512,8 +3509,12 @@ unsigned BytesPerElement = EltVT.getSizeInBits()/8; SmallVector ResultMask; - for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { - unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i]; + for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) { + unsigned SrcElt; + if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF) + SrcElt = 0; + else + SrcElt = cast(PermMask.getOperand(i))->getZExtValue(); for (unsigned j = 0; j != BytesPerElement; ++j) ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j, @@ -3703,12 +3704,13 @@ OddParts = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OddParts); // Merge the results together. - int Ops[16]; + SDValue Ops[16]; for (unsigned i = 0; i != 8; ++i) { - Ops[i*2 ] = 2*i+1; - Ops[i*2+1] = 2*i+1+16; + Ops[i*2 ] = DAG.getConstant(2*i+1, MVT::i8); + Ops[i*2+1] = DAG.getConstant(2*i+1+16, MVT::i8); } - return DAG.getVectorShuffle(MVT::v16i8, dl, EvenParts, OddParts, Ops); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v16i8, EvenParts, OddParts, + DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8, Ops, 16)); } else { assert(0 && "Unknown mul to lower!"); abort(); Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h (original) +++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h Fri Apr 24 07:40:33 2009 @@ -175,21 +175,19 @@ namespace PPC { /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUHUM instruction. - bool isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary); + bool isVPKUHUMShuffleMask(SDNode *N, bool isUnary); /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUWUM instruction. - bool isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary); + bool isVPKUWUMShuffleMask(SDNode *N, bool isUnary); /// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for /// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). - bool isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, - bool isUnary); + bool isVMRGLShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary); /// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). - bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, - bool isUnary); + bool isVMRGHShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary); /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// amount, otherwise return -1. @@ -198,7 +196,7 @@ /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a splat of a single element that is suitable for input to /// VSPLTB/VSPLTH/VSPLTW. - bool isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize); + bool isSplatShuffleMask(SDNode *N, unsigned EltSize); /// isAllNegativeZeroVector - Returns true if all elements of build_vector /// are -0.0. Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td (original) +++ llvm/trunk/lib/Target/PowerPC/PPCInstrAltivec.td Fri Apr 24 07:40:33 2009 @@ -15,118 +15,96 @@ // Altivec transformation functions and pattern fragments. // - -def vpkuhum_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVPKUHUMShuffleMask(cast(N), false); +/// VPKUHUM_shuffle_mask/VPKUWUM_shuffle_mask - Return true if this is a valid +/// shuffle mask for the VPKUHUM or VPKUWUM instructions. +def VPKUHUM_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVPKUHUMShuffleMask(N, false); }]>; -def vpkuwum_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVPKUWUMShuffleMask(cast(N), false); +def VPKUWUM_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVPKUWUMShuffleMask(N, false); }]>; -def vpkuhum_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVPKUHUMShuffleMask(cast(N), true); + +def VPKUHUM_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVPKUHUMShuffleMask(N, true); }]>; -def vpkuwum_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVPKUWUMShuffleMask(cast(N), true); +def VPKUWUM_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVPKUWUMShuffleMask(N, true); }]>; -def vmrglb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGLShuffleMask(cast(N), 1, false); +def VMRGLB_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 1, false); }]>; -def vmrglh_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGLShuffleMask(cast(N), 2, false); +def VMRGLH_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 2, false); }]>; -def vmrglw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGLShuffleMask(cast(N), 4, false); +def VMRGLW_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 4, false); }]>; -def vmrghb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGHShuffleMask(cast(N), 1, false); +def VMRGHB_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 1, false); }]>; -def vmrghh_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGHShuffleMask(cast(N), 2, false); +def VMRGHH_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 2, false); }]>; -def vmrghw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGHShuffleMask(cast(N), 4, false); +def VMRGHW_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 4, false); }]>; - -def vmrglb_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGLShuffleMask(cast(N), 1, true); +def VMRGLB_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 1, true); }]>; -def vmrglh_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGLShuffleMask(cast(N), 2, true); +def VMRGLH_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 2, true); }]>; -def vmrglw_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGLShuffleMask(cast(N), 4, true); +def VMRGLW_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGLShuffleMask(N, 4, true); }]>; -def vmrghb_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGHShuffleMask(cast(N), 1, true); +def VMRGHB_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 1, true); }]>; -def vmrghh_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGHShuffleMask(cast(N), 2, true); +def VMRGHH_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 2, true); }]>; -def vmrghw_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isVMRGHShuffleMask(cast(N), 4, true); +def VMRGHW_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVMRGHShuffleMask(N, 4, true); }]>; - -def VSLDOI_get_imm : SDNodeXForm; -def vsldoi_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ +def VSLDOI_shuffle_mask : PatLeaf<(build_vector), [{ return PPC::isVSLDOIShuffleMask(N, false) != -1; }], VSLDOI_get_imm>; - /// VSLDOI_unary* - These are used to match vsldoi(X,X), which is turned into /// vector_shuffle(X,undef,mask) by the dag combiner. -def VSLDOI_unary_get_imm : SDNodeXForm; -def vsldoi_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ +def VSLDOI_unary_shuffle_mask : PatLeaf<(build_vector), [{ return PPC::isVSLDOIShuffleMask(N, true) != -1; }], VSLDOI_unary_get_imm>; // VSPLT*_get_imm xform function: convert vector_shuffle mask to VSPLT* imm. -def VSPLTB_get_imm : SDNodeXForm; -def vspltb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isSplatShuffleMask(cast(N), 1); +def VSPLTB_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isSplatShuffleMask(N, 1); }], VSPLTB_get_imm>; -def VSPLTH_get_imm : SDNodeXForm; -def vsplth_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isSplatShuffleMask(cast(N), 2); +def VSPLTH_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isSplatShuffleMask(N, 2); }], VSPLTH_get_imm>; -def VSPLTW_get_imm : SDNodeXForm; -def vspltw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return PPC::isSplatShuffleMask(cast(N), 4); +def VSPLTW_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isSplatShuffleMask(N, 4); }], VSPLTW_get_imm>; @@ -290,7 +268,8 @@ def VSLDOI : VAForm_2<44, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB, u5imm:$SH), "vsldoi $vD, $vA, $vB, $SH", VecFP, [(set VRRC:$vD, - (vsldoi_shuffle:$SH (v16i8 VRRC:$vA), VRRC:$vB))]>; + (vector_shuffle (v16i8 VRRC:$vA), VRRC:$vB, + VSLDOI_shuffle_mask:$SH))]>; // VX-Form instructions. AltiVec arithmetic ops. def VADDFP : VXForm_1<10, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), @@ -366,22 +345,28 @@ def VMRGHB : VXForm_1< 12, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrghb $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vmrghb_shuffle VRRC:$vA, VRRC:$vB))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGHB_shuffle_mask))]>; def VMRGHH : VXForm_1< 76, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrghh $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vmrghh_shuffle VRRC:$vA, VRRC:$vB))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGHH_shuffle_mask))]>; def VMRGHW : VXForm_1<140, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrghw $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vmrghw_shuffle VRRC:$vA, VRRC:$vB))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGHW_shuffle_mask))]>; def VMRGLB : VXForm_1<268, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrglb $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vmrglb_shuffle VRRC:$vA, VRRC:$vB))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGLB_shuffle_mask))]>; def VMRGLH : VXForm_1<332, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrglh $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vmrglh_shuffle VRRC:$vA, VRRC:$vB))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGLH_shuffle_mask))]>; def VMRGLW : VXForm_1<396, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vmrglw $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, (vmrglw_shuffle VRRC:$vA, VRRC:$vB))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VMRGLW_shuffle_mask))]>; def VMSUMMBM : VA1a_Int<37, "vmsummbm", int_ppc_altivec_vmsummbm>; def VMSUMSHM : VA1a_Int<40, "vmsumshm", int_ppc_altivec_vmsumshm>; @@ -455,16 +440,16 @@ def VSPLTB : VXForm_1<524, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), "vspltb $vD, $vB, $UIMM", VecPerm, - [(set VRRC:$vD, - (vspltb_shuffle:$UIMM (v16i8 VRRC:$vB), (undef)))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef), + VSPLTB_shuffle_mask:$UIMM))]>; def VSPLTH : VXForm_1<588, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), "vsplth $vD, $vB, $UIMM", VecPerm, - [(set VRRC:$vD, - (vsplth_shuffle:$UIMM (v16i8 VRRC:$vB), (undef)))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef), + VSPLTH_shuffle_mask:$UIMM))]>; def VSPLTW : VXForm_1<652, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), "vspltw $vD, $vB, $UIMM", VecPerm, - [(set VRRC:$vD, - (vspltw_shuffle:$UIMM (v16i8 VRRC:$vB), (undef)))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef), + VSPLTW_shuffle_mask:$UIMM))]>; def VSR : VX1_Int< 708, "vsr" , int_ppc_altivec_vsr>; def VSRO : VX1_Int<1100, "vsro" , int_ppc_altivec_vsro>; @@ -494,13 +479,13 @@ def VPKSWUS : VX1_Int<334, "vpkswus", int_ppc_altivec_vpkswus>; def VPKUHUM : VXForm_1<14, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vpkuhum $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, - (vpkuhum_shuffle (v16i8 VRRC:$vA), VRRC:$vB))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VPKUHUM_shuffle_mask))]>; def VPKUHUS : VX1_Int<142, "vpkuhus", int_ppc_altivec_vpkuhus>; def VPKUWUM : VXForm_1<78, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), "vpkuwum $vD, $vA, $vB", VecFP, - [(set VRRC:$vD, - (vpkuwum_shuffle (v16i8 VRRC:$vA), VRRC:$vB))]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VPKUWUM_shuffle_mask))]>; def VPKUWUS : VX1_Int<206, "vpkuwus", int_ppc_altivec_vpkuwus>; // Vector Unpack. @@ -618,25 +603,25 @@ // Shuffles. // Match vsldoi(x,x), vpkuwum(x,x), vpkuhum(x,x) -def:Pat<(vsldoi_unary_shuffle:$in (v16i8 VRRC:$vA), undef), - (VSLDOI VRRC:$vA, VRRC:$vA, (VSLDOI_unary_get_imm VRRC:$in))>; -def:Pat<(vpkuwum_unary_shuffle (v16i8 VRRC:$vA), undef), +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VSLDOI_unary_shuffle_mask:$in), + (VSLDOI VRRC:$vA, VRRC:$vA, VSLDOI_unary_shuffle_mask:$in)>; +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef,VPKUWUM_unary_shuffle_mask:$in), (VPKUWUM VRRC:$vA, VRRC:$vA)>; -def:Pat<(vpkuhum_unary_shuffle (v16i8 VRRC:$vA), undef), +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef,VPKUHUM_unary_shuffle_mask:$in), (VPKUHUM VRRC:$vA, VRRC:$vA)>; // Match vmrg*(x,x) -def:Pat<(vmrglb_unary_shuffle (v16i8 VRRC:$vA), undef), +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGLB_unary_shuffle_mask:$in), (VMRGLB VRRC:$vA, VRRC:$vA)>; -def:Pat<(vmrglh_unary_shuffle (v16i8 VRRC:$vA), undef), +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGLH_unary_shuffle_mask:$in), (VMRGLH VRRC:$vA, VRRC:$vA)>; -def:Pat<(vmrglw_unary_shuffle (v16i8 VRRC:$vA), undef), +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGLW_unary_shuffle_mask:$in), (VMRGLW VRRC:$vA, VRRC:$vA)>; -def:Pat<(vmrghb_unary_shuffle (v16i8 VRRC:$vA), undef), +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHB_unary_shuffle_mask:$in), (VMRGHB VRRC:$vA, VRRC:$vA)>; -def:Pat<(vmrghh_unary_shuffle (v16i8 VRRC:$vA), undef), +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHH_unary_shuffle_mask:$in), (VMRGHH VRRC:$vA, VRRC:$vA)>; -def:Pat<(vmrghw_unary_shuffle (v16i8 VRRC:$vA), undef), +def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHW_unary_shuffle_mask:$in), (VMRGHW VRRC:$vA, VRRC:$vA)>; // Logical Operations Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Apr 24 07:40:33 2009 @@ -45,8 +45,7 @@ DisableMMX("disable-mmx", cl::Hidden, cl::desc("Disable use of MMX")); // Forward declarations. -static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1, - SDValue V2); +static SDValue getMOVLMask(unsigned NumElems, SelectionDAG &DAG, DebugLoc dl); X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) : TargetLowering(TM) { @@ -1668,7 +1667,9 @@ // Special case: passing MMX values in XMM registers. Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, Arg); Arg = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2i64, Arg); - Arg = getMOVL(DAG, dl, MVT::v2i64, DAG.getUNDEF(MVT::v2i64), Arg); + Arg = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v2i64, + DAG.getUNDEF(MVT::v2i64), Arg, + getMOVLMask(2, DAG, dl)); break; } } @@ -2137,156 +2138,186 @@ } } -/// isUndefOrInRange - Return true if Val is undef or if its value falls within -/// the specified range (L, H]. -static bool isUndefOrInRange(int Val, int Low, int Hi) { - return (Val < 0) || (Val >= Low && Val < Hi); +/// isUndefOrInRange - Op is either an undef node or a ConstantSDNode. Return +/// true if Op is undef or if its value falls within the specified range (L, H]. +static bool isUndefOrInRange(SDValue Op, unsigned Low, unsigned Hi) { + if (Op.getOpcode() == ISD::UNDEF) + return true; + + unsigned Val = cast(Op)->getZExtValue(); + return (Val >= Low && Val < Hi); } -/// isUndefOrEqual - Val is either less than zero (undef) or equal to the -/// specified value. -static bool isUndefOrEqual(int Val, int CmpVal) { - if (Val < 0 || Val == CmpVal) +/// isUndefOrEqual - Op is either an undef node or a ConstantSDNode. Return +/// true if Op is undef or if its value equal to the specified value. +static bool isUndefOrEqual(SDValue Op, unsigned Val) { + if (Op.getOpcode() == ISD::UNDEF) return true; - return false; + return cast(Op)->getZExtValue() == Val; } -/// isPSHUFDMask - Return true if the node specifies a shuffle of elements that -/// is suitable for input to PSHUFD or PSHUFW. That is, it doesn't reference -/// the second operand. -static bool isPSHUFDMask(const int *Mask, MVT VT) { - if (VT == MVT::v4f32 || VT == MVT::v4i32 || VT == MVT::v4i16) - return (Mask[0] < 4 && Mask[1] < 4 && Mask[2] < 4 && Mask[3] < 4); - if (VT == MVT::v2f64 || VT == MVT::v2i64) - return (Mask[0] < 2 && Mask[1] < 2); - return false; -} +/// isPSHUFDMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to PSHUFD. +bool X86::isPSHUFDMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); -bool X86::isPSHUFDMask(ShuffleVectorSDNode *N) { - return ::isPSHUFDMask(N->getMask(), N->getValueType(0)); + if (N->getNumOperands() != 2 && N->getNumOperands() != 4) + return false; + + // Check if the value doesn't reference the second vector. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + if (cast(Arg)->getZExtValue() >= e) + return false; + } + + return true; } -/// isPSHUFHWMask - Return true if the node specifies a shuffle of elements that -/// is suitable for input to PSHUFHW. -static bool isPSHUFHWMask(const int *Mask, MVT VT) { - if (VT != MVT::v8i16) +/// isPSHUFHWMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to PSHUFHW. +bool X86::isPSHUFHWMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + if (N->getNumOperands() != 8) return false; - - // Lower quadword copied in order or undef. - for (int i = 0; i != 4; ++i) - if (Mask[i] >= 0 && Mask[i] != i) + + // Lower quadword copied in order. + for (unsigned i = 0; i != 4; ++i) { + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + if (cast(Arg)->getZExtValue() != i) return false; - + } + // Upper quadword shuffled. - for (int i = 4; i != 8; ++i) - if (Mask[i] >= 0 && (Mask[i] < 4 || Mask[i] > 7)) + for (unsigned i = 4; i != 8; ++i) { + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + unsigned Val = cast(Arg)->getZExtValue(); + if (Val < 4 || Val > 7) return false; - + } + return true; } -bool X86::isPSHUFHWMask(ShuffleVectorSDNode *N) { - return ::isPSHUFHWMask(N->getMask(), N->getValueType(0)); -} +/// isPSHUFLWMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to PSHUFLW. +bool X86::isPSHUFLWMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); -/// isPSHUFLWMask - Return true if the node specifies a shuffle of elements that -/// is suitable for input to PSHUFLW. -static bool isPSHUFLWMask(const int *Mask, MVT VT) { - if (VT != MVT::v8i16) + if (N->getNumOperands() != 8) return false; - + // Upper quadword copied in order. - for (int i = 4; i != 8; ++i) - if (Mask[i] >= 0 && Mask[i] != i) + for (unsigned i = 4; i != 8; ++i) + if (!isUndefOrEqual(N->getOperand(i), i)) return false; - + // Lower quadword shuffled. - for (int i = 0; i != 4; ++i) - if (Mask[i] >= 4) + for (unsigned i = 0; i != 4; ++i) + if (!isUndefOrInRange(N->getOperand(i), 0, 4)) return false; - - return true; -} -bool X86::isPSHUFLWMask(ShuffleVectorSDNode *N) { - return ::isPSHUFLWMask(N->getMask(), N->getValueType(0)); + return true; } /// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to SHUFP*. -static bool isSHUFPMask(const int *Mask, MVT VT) { - int NumElems = VT.getVectorNumElements(); - if (NumElems != 2 && NumElems != 4) - return false; - - int Half = NumElems / 2; - for (int i = 0; i < Half; ++i) - if (!isUndefOrInRange(Mask[i], 0, NumElems)) +template +static bool isSHUFPMask(SDOperand *Elems, unsigned NumElems) { + if (NumElems != 2 && NumElems != 4) return false; + + unsigned Half = NumElems / 2; + for (unsigned i = 0; i < Half; ++i) + if (!isUndefOrInRange(Elems[i], 0, NumElems)) return false; - for (int i = Half; i < NumElems; ++i) - if (!isUndefOrInRange(Mask[i], NumElems, NumElems*2)) + for (unsigned i = Half; i < NumElems; ++i) + if (!isUndefOrInRange(Elems[i], NumElems, NumElems*2)) return false; - + return true; } -bool X86::isSHUFPMask(ShuffleVectorSDNode *N) { - return ::isSHUFPMask(N->getMask(), N->getValueType(0)); +bool X86::isSHUFPMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + return ::isSHUFPMask(N->op_begin(), N->getNumOperands()); } /// isCommutedSHUFP - Returns true if the shuffle mask is exactly /// the reverse of what x86 shuffles want. x86 shuffles requires the lower /// half elements to come from vector 1 (which would equal the dest.) and /// the upper half to come from vector 2. -static bool isCommutedSHUFPMask(const int *Mask, MVT VT) { - int NumElems = VT.getVectorNumElements(); - - if (NumElems != 2 && NumElems != 4) - return false; - - int Half = NumElems / 2; - for (int i = 0; i < Half; ++i) - if (!isUndefOrInRange(Mask[i], NumElems, NumElems*2)) +template +static bool isCommutedSHUFP(SDOperand *Ops, unsigned NumOps) { + if (NumOps != 2 && NumOps != 4) return false; + + unsigned Half = NumOps / 2; + for (unsigned i = 0; i < Half; ++i) + if (!isUndefOrInRange(Ops[i], NumOps, NumOps*2)) return false; - for (int i = Half; i < NumElems; ++i) - if (!isUndefOrInRange(Mask[i], 0, NumElems)) + for (unsigned i = Half; i < NumOps; ++i) + if (!isUndefOrInRange(Ops[i], 0, NumOps)) return false; return true; } -static bool isCommutedSHUFP(ShuffleVectorSDNode *N) { - return isCommutedSHUFPMask(N->getMask(), N->getValueType(0)); +static bool isCommutedSHUFP(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + return isCommutedSHUFP(N->op_begin(), N->getNumOperands()); } /// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVHLPS. -bool X86::isMOVHLPSMask(ShuffleVectorSDNode *N) { - if (N->getValueType(0).getVectorNumElements() != 4) +bool X86::isMOVHLPSMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + if (N->getNumOperands() != 4) return false; // Expect bit0 == 6, bit1 == 7, bit2 == 2, bit3 == 3 - const int *Mask = N->getMask(); - return isUndefOrEqual(Mask[0], 6) && - isUndefOrEqual(Mask[1], 7) && - isUndefOrEqual(Mask[2], 2) && - isUndefOrEqual(Mask[3], 3); + return isUndefOrEqual(N->getOperand(0), 6) && + isUndefOrEqual(N->getOperand(1), 7) && + isUndefOrEqual(N->getOperand(2), 2) && + isUndefOrEqual(N->getOperand(3), 3); +} + +/// isMOVHLPS_v_undef_Mask - Special case of isMOVHLPSMask for canonical form +/// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef, +/// <2, 3, 2, 3> +bool X86::isMOVHLPS_v_undef_Mask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + if (N->getNumOperands() != 4) + return false; + + // Expect bit0 == 2, bit1 == 3, bit2 == 2, bit3 == 3 + return isUndefOrEqual(N->getOperand(0), 2) && + isUndefOrEqual(N->getOperand(1), 3) && + isUndefOrEqual(N->getOperand(2), 2) && + isUndefOrEqual(N->getOperand(3), 3); } /// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVLP{S|D}. -bool X86::isMOVLPMask(ShuffleVectorSDNode *N) { - unsigned NumElems = N->getValueType(0).getVectorNumElements(); +bool X86::isMOVLPMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + unsigned NumElems = N->getNumOperands(); if (NumElems != 2 && NumElems != 4) return false; - const int *Mask = N->getMask(); for (unsigned i = 0; i < NumElems/2; ++i) - if (!isUndefOrEqual(Mask[i], i + NumElems)) + if (!isUndefOrEqual(N->getOperand(i), i + NumElems)) return false; for (unsigned i = NumElems/2; i < NumElems; ++i) - if (!isUndefOrEqual(Mask[i], i)) + if (!isUndefOrEqual(N->getOperand(i), i)) return false; return true; @@ -2295,49 +2326,37 @@ /// isMOVHPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVHP{S|D} /// and MOVLHPS. -bool X86::isMOVHPMask(ShuffleVectorSDNode *N) { - unsigned NumElems = N->getValueType(0).getVectorNumElements(); +bool X86::isMOVHPMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + unsigned NumElems = N->getNumOperands(); if (NumElems != 2 && NumElems != 4) return false; - const int *Mask = N->getMask(); for (unsigned i = 0; i < NumElems/2; ++i) - if (!isUndefOrEqual(Mask[i], i)) + if (!isUndefOrEqual(N->getOperand(i), i)) return false; - for (unsigned i = 0; i < NumElems/2; ++i) - if (!isUndefOrEqual(Mask[i + NumElems/2], i + NumElems)) + for (unsigned i = 0; i < NumElems/2; ++i) { + SDValue Arg = N->getOperand(i + NumElems/2); + if (!isUndefOrEqual(Arg, i + NumElems)) return false; + } return true; } -/// isMOVHLPS_v_undef_Mask - Special case of isMOVHLPSMask for canonical form -/// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef, -/// <2, 3, 2, 3> -bool X86::isMOVHLPS_v_undef_Mask(ShuffleVectorSDNode *N) { - unsigned NumElems = N->getValueType(0).getVectorNumElements(); - - if (NumElems != 4) - return false; - - // Expect bit0 == 2, bit1 == 3, bit2 == 2, bit3 == 3 - const int *Mask = N->getMask(); - return isUndefOrEqual(Mask[0], 2) && isUndefOrEqual(Mask[1], 3) && - isUndefOrEqual(Mask[2], 2) && isUndefOrEqual(Mask[3], 3); -} - /// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKL. -static bool isUNPCKLMask(const int *Mask, MVT VT, bool V2IsSplat = false) { - int NumElts = VT.getVectorNumElements(); +template +bool static isUNPCKLMask(SDOperand *Elts, unsigned NumElts, + bool V2IsSplat = false) { if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) return false; - - for (int i = 0, j = 0; i != NumElts; i += 2, ++j) { - int BitI = Mask[i]; - int BitI1 = Mask[i+1]; + + for (unsigned i = 0, j = 0; i != NumElts; i += 2, ++j) { + SDValue BitI = Elts[i]; + SDValue BitI1 = Elts[i+1]; if (!isUndefOrEqual(BitI, j)) return false; if (V2IsSplat) { @@ -2348,23 +2367,26 @@ return false; } } + return true; } -bool X86::isUNPCKLMask(ShuffleVectorSDNode *N, bool V2IsSplat) { - return ::isUNPCKLMask(N->getMask(), N->getValueType(0), V2IsSplat); +bool X86::isUNPCKLMask(SDNode *N, bool V2IsSplat) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + return ::isUNPCKLMask(N->op_begin(), N->getNumOperands(), V2IsSplat); } /// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKH. -static bool isUNPCKHMask(const int *Mask, MVT VT, bool V2IsSplat = false) { - int NumElts = VT.getVectorNumElements(); +template +bool static isUNPCKHMask(SDOperand *Elts, unsigned NumElts, + bool V2IsSplat = false) { if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) return false; - - for (int i = 0, j = 0; i != NumElts; i += 2, ++j) { - int BitI = Mask[i]; - int BitI1 = Mask[i+1]; + + for (unsigned i = 0, j = 0; i != NumElts; i += 2, ++j) { + SDValue BitI = Elts[i]; + SDValue BitI1 = Elts[i+1]; if (!isUndefOrEqual(BitI, j + NumElts/2)) return false; if (V2IsSplat) { @@ -2375,166 +2397,270 @@ return false; } } + return true; } -bool X86::isUNPCKHMask(ShuffleVectorSDNode *N, bool V2IsSplat) { - return ::isUNPCKHMask(N->getMask(), N->getValueType(0), V2IsSplat); +bool X86::isUNPCKHMask(SDNode *N, bool V2IsSplat) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + return ::isUNPCKHMask(N->op_begin(), N->getNumOperands(), V2IsSplat); } /// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form /// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef, /// <0, 0, 1, 1> -static bool isUNPCKL_v_undef_Mask(const int *Mask, MVT VT) { - int NumElems = VT.getVectorNumElements(); +bool X86::isUNPCKL_v_undef_Mask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + unsigned NumElems = N->getNumOperands(); if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16) return false; - - for (int i = 0, j = 0; i != NumElems; i += 2, ++j) { - int BitI = Mask[i]; - int BitI1 = Mask[i+1]; + + for (unsigned i = 0, j = 0; i != NumElems; i += 2, ++j) { + SDValue BitI = N->getOperand(i); + SDValue BitI1 = N->getOperand(i+1); + if (!isUndefOrEqual(BitI, j)) return false; if (!isUndefOrEqual(BitI1, j)) return false; } - return true; -} -bool X86::isUNPCKL_v_undef_Mask(ShuffleVectorSDNode *N) { - return ::isUNPCKL_v_undef_Mask(N->getMask(), N->getValueType(0)); + return true; } /// isUNPCKH_v_undef_Mask - Special case of isUNPCKHMask for canonical form /// of vector_shuffle v, v, <2, 6, 3, 7>, i.e. vector_shuffle v, undef, /// <2, 2, 3, 3> -static bool isUNPCKH_v_undef_Mask(const int *Mask, MVT VT) { - int NumElems = VT.getVectorNumElements(); +bool X86::isUNPCKH_v_undef_Mask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + unsigned NumElems = N->getNumOperands(); if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16) return false; - - for (int i = 0, j = NumElems / 2; i != NumElems; i += 2, ++j) { - int BitI = Mask[i]; - int BitI1 = Mask[i+1]; + + for (unsigned i = 0, j = NumElems / 2; i != NumElems; i += 2, ++j) { + SDValue BitI = N->getOperand(i); + SDValue BitI1 = N->getOperand(i + 1); + if (!isUndefOrEqual(BitI, j)) return false; if (!isUndefOrEqual(BitI1, j)) return false; } - return true; -} -bool X86::isUNPCKH_v_undef_Mask(ShuffleVectorSDNode *N) { - return ::isUNPCKH_v_undef_Mask(N->getMask(), N->getValueType(0)); + return true; } /// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSS, /// MOVSD, and MOVD, i.e. setting the lowest element. -static bool isMOVLMask(const int *Mask, MVT VT) { - int NumElts = VT.getVectorNumElements(); +template +static bool isMOVLMask(SDOperand *Elts, unsigned NumElts) { if (NumElts != 2 && NumElts != 4) return false; - - if (!isUndefOrEqual(Mask[0], NumElts)) + + if (!isUndefOrEqual(Elts[0], NumElts)) return false; - - for (int i = 1; i < NumElts; ++i) - if (!isUndefOrEqual(Mask[i], i)) + + for (unsigned i = 1; i < NumElts; ++i) { + if (!isUndefOrEqual(Elts[i], i)) return false; - + } + return true; } -bool X86::isMOVLMask(ShuffleVectorSDNode *N) { - return ::isMOVLMask(N->getMask(), N->getValueType(0)); +bool X86::isMOVLMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + return ::isMOVLMask(N->op_begin(), N->getNumOperands()); } /// isCommutedMOVL - Returns true if the shuffle mask is except the reverse /// of what x86 movss want. X86 movs requires the lowest element to be lowest /// element of vector 2 and the other elements to come from vector 1 in order. -static bool isCommutedMOVLMask(const int *Mask, MVT VT, bool V2IsSplat = false, - bool V2IsUndef = false) { - int NumOps = VT.getVectorNumElements(); +template +static bool isCommutedMOVL(SDOperand *Ops, unsigned NumOps, + bool V2IsSplat = false, + bool V2IsUndef = false) { if (NumOps != 2 && NumOps != 4 && NumOps != 8 && NumOps != 16) return false; - - if (!isUndefOrEqual(Mask[0], 0)) + + if (!isUndefOrEqual(Ops[0], 0)) return false; - - for (int i = 1; i < NumOps; ++i) - if (!(isUndefOrEqual(Mask[i], i+NumOps) || - (V2IsUndef && isUndefOrInRange(Mask[i], NumOps, NumOps*2)) || - (V2IsSplat && isUndefOrEqual(Mask[i], NumOps)))) + + for (unsigned i = 1; i < NumOps; ++i) { + SDValue Arg = Ops[i]; + if (!(isUndefOrEqual(Arg, i+NumOps) || + (V2IsUndef && isUndefOrInRange(Arg, NumOps, NumOps*2)) || + (V2IsSplat && isUndefOrEqual(Arg, NumOps)))) return false; - + } + return true; } -static bool isCommutedMOVL(ShuffleVectorSDNode *N, bool V2IsSplat = false, +static bool isCommutedMOVL(SDNode *N, bool V2IsSplat = false, bool V2IsUndef = false) { - return isCommutedMOVLMask(N->getMask(), N->getValueType(0), V2IsSplat, - V2IsUndef); + assert(N->getOpcode() == ISD::BUILD_VECTOR); + return isCommutedMOVL(N->op_begin(), N->getNumOperands(), + V2IsSplat, V2IsUndef); } /// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSHDUP. -bool X86::isMOVSHDUPMask(ShuffleVectorSDNode *N) { - if (N->getValueType(0).getVectorNumElements() != 4) +bool X86::isMOVSHDUPMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + if (N->getNumOperands() != 4) return false; // Expect 1, 1, 3, 3 - const int *Mask = N->getMask(); - for (unsigned i = 0; i < 2; ++i) - if (Mask[i] >=0 && Mask[i] != 1) - return false; + for (unsigned i = 0; i < 2; ++i) { + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + unsigned Val = cast(Arg)->getZExtValue(); + if (Val != 1) return false; + } bool HasHi = false; for (unsigned i = 2; i < 4; ++i) { - if (Mask[i] >= 0 && Mask[i] != 3) - return false; - if (Mask[i] == 3) - HasHi = true; + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + unsigned Val = cast(Arg)->getZExtValue(); + if (Val != 3) return false; + HasHi = true; } + // Don't use movshdup if it can be done with a shufps. - // FIXME: verify that matching u, u, 3, 3 is what we want. return HasHi; } /// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSLDUP. -bool X86::isMOVSLDUPMask(ShuffleVectorSDNode *N) { - if (N->getValueType(0).getVectorNumElements() != 4) +bool X86::isMOVSLDUPMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + if (N->getNumOperands() != 4) return false; // Expect 0, 0, 2, 2 - const int *Mask = N->getMask(); - for (unsigned i = 0; i < 2; ++i) - if (Mask[i] > 0) - return false; + for (unsigned i = 0; i < 2; ++i) { + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + unsigned Val = cast(Arg)->getZExtValue(); + if (Val != 0) return false; + } bool HasHi = false; for (unsigned i = 2; i < 4; ++i) { - if (Mask[i] >= 0 && Mask[i] != 2) - return false; - if (Mask[i] == 2) - HasHi = true; + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + unsigned Val = cast(Arg)->getZExtValue(); + if (Val != 2) return false; + HasHi = true; } - // Don't use movsldup if it can be done with a shufps. + + // Don't use movshdup if it can be done with a shufps. return HasHi; } +/// isIdentityMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a identity operation on the LHS or RHS. +static bool isIdentityMask(SDNode *N, bool RHS = false) { + unsigned NumElems = N->getNumOperands(); + for (unsigned i = 0; i < NumElems; ++i) + if (!isUndefOrEqual(N->getOperand(i), i + (RHS ? NumElems : 0))) + return false; + return true; +} + +/// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand specifies +/// a splat of a single element. +static bool isSplatMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + // This is a splat operation if each element of the permute is the same, and + // if the value doesn't reference the second vector. + unsigned NumElems = N->getNumOperands(); + SDValue ElementBase; + unsigned i = 0; + for (; i != NumElems; ++i) { + SDValue Elt = N->getOperand(i); + if (isa(Elt)) { + ElementBase = Elt; + break; + } + } + + if (!ElementBase.getNode()) + return false; + + for (; i != NumElems; ++i) { + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + if (Arg != ElementBase) return false; + } + + // Make sure it is a splat of the first vector operand. + return cast(ElementBase)->getZExtValue() < NumElems; +} + +/// getSplatMaskEltNo - Given a splat mask, return the index to the element +/// we want to splat. +static SDValue getSplatMaskEltNo(SDNode *N) { + assert(isSplatMask(N) && "Not a splat mask"); + unsigned NumElems = N->getNumOperands(); + SDValue ElementBase; + unsigned i = 0; + for (; i != NumElems; ++i) { + SDValue Elt = N->getOperand(i); + if (isa(Elt)) + return Elt; + } + assert(0 && " No splat value found!"); + return SDValue(); +} + + +/// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand specifies +/// a splat of a single element and it's a 2 or 4 element mask. +bool X86::isSplatMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + // We can only splat 64-bit, and 32-bit quantities with a single instruction. + if (N->getNumOperands() != 4 && N->getNumOperands() != 2) + return false; + return ::isSplatMask(N); +} + +/// isSplatLoMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a splat of zero element. +bool X86::isSplatLoMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i) + if (!isUndefOrEqual(N->getOperand(i), 0)) + return false; + return true; +} + /// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVDDUP. -bool X86::isMOVDDUPMask(ShuffleVectorSDNode *N) { - int e = N->getValueType(0).getVectorNumElements() / 2; - const int *Mask = N->getMask(); - - for (int i = 0; i < e; ++i) - if (!isUndefOrEqual(Mask[i], i)) +bool X86::isMOVDDUPMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + unsigned e = N->getNumOperands() / 2; + for (unsigned i = 0; i < e; ++i) + if (!isUndefOrEqual(N->getOperand(i), i)) return false; - for (int i = 0; i < e; ++i) - if (!isUndefOrEqual(Mask[e+i], i)) + for (unsigned i = 0; i < e; ++i) + if (!isUndefOrEqual(N->getOperand(e+i), i)) return false; return true; } @@ -2543,20 +2669,20 @@ /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUF* and SHUFP* /// instructions. unsigned X86::getShuffleSHUFImmediate(SDNode *N) { - ShuffleVectorSDNode *SVOp = cast(N); - int NumOperands = SVOp->getValueType(0).getVectorNumElements(); - const int *MaskP = SVOp->getMask(); - + unsigned NumOperands = N->getNumOperands(); unsigned Shift = (NumOperands == 4) ? 2 : 1; unsigned Mask = 0; - for (int i = 0; i < NumOperands; ++i) { - int Val = MaskP[NumOperands-i-1]; - if (Val < 0) Val = 0; + for (unsigned i = 0; i < NumOperands; ++i) { + unsigned Val = 0; + SDValue Arg = N->getOperand(NumOperands-i-1); + if (Arg.getOpcode() != ISD::UNDEF) + Val = cast(Arg)->getZExtValue(); if (Val >= NumOperands) Val -= NumOperands; Mask |= Val; if (i != NumOperands - 1) Mask <<= Shift; } + return Mask; } @@ -2564,16 +2690,19 @@ /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUFHW /// instructions. unsigned X86::getShufflePSHUFHWImmediate(SDNode *N) { - const int *MaskP = cast(N)->getMask(); unsigned Mask = 0; // 8 nodes, but we only care about the last 4. for (unsigned i = 7; i >= 4; --i) { - int Val = MaskP[i]; - if (Val >= 0) + unsigned Val = 0; + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() != ISD::UNDEF) { + Val = cast(Arg)->getZExtValue(); Mask |= (Val - 4); + } if (i != 4) Mask <<= 2; } + return Mask; } @@ -2581,71 +2710,90 @@ /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUFLW /// instructions. unsigned X86::getShufflePSHUFLWImmediate(SDNode *N) { - const int *MaskP = cast(N)->getMask(); unsigned Mask = 0; // 8 nodes, but we only care about the first 4. for (int i = 3; i >= 0; --i) { - int Val = MaskP[i]; - if (Val >= 0) - Mask |= Val; + unsigned Val = 0; + SDValue Arg = N->getOperand(i); + if (Arg.getOpcode() != ISD::UNDEF) + Val = cast(Arg)->getZExtValue(); + Mask |= Val; if (i != 0) Mask <<= 2; } + return Mask; } -/// CommuteVectorShuffle - Swap vector_shuffle operands as well as values in -/// their permute mask. -static SDValue CommuteVectorShuffle(ShuffleVectorSDNode *SVOp, - SelectionDAG &DAG) { - MVT VT = SVOp->getValueType(0); - int NumElems = VT.getVectorNumElements(); - const int *Mask = SVOp->getMask(); - SmallVector MaskVec; - - for (int i = 0; i != NumElems; ++i) { - int idx = Mask[i]; - if (idx < 0) - MaskVec.push_back(idx); - else if (idx < NumElems) - MaskVec.push_back(idx + NumElems); +/// CommuteVectorShuffle - Swap vector_shuffle operands as well as +/// values in ther permute mask. +static SDValue CommuteVectorShuffle(SDValue Op, SDValue &V1, + SDValue &V2, SDValue &Mask, + SelectionDAG &DAG) { + MVT VT = Op.getValueType(); + MVT MaskVT = Mask.getValueType(); + MVT EltVT = MaskVT.getVectorElementType(); + unsigned NumElems = Mask.getNumOperands(); + SmallVector MaskVec; + DebugLoc dl = Op.getDebugLoc(); + + for (unsigned i = 0; i != NumElems; ++i) { + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) { + MaskVec.push_back(DAG.getUNDEF(EltVT)); + continue; + } + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + unsigned Val = cast(Arg)->getZExtValue(); + if (Val < NumElems) + MaskVec.push_back(DAG.getConstant(Val + NumElems, EltVT)); else - MaskVec.push_back(idx - NumElems); + MaskVec.push_back(DAG.getConstant(Val - NumElems, EltVT)); } - return DAG.getVectorShuffle(VT, SVOp->getDebugLoc(), SVOp->getOperand(1), - SVOp->getOperand(0), &MaskVec[0]); + + std::swap(V1, V2); + Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, &MaskVec[0], NumElems); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, Mask); } /// CommuteVectorShuffleMask - Change values in a shuffle permute mask assuming /// the two vector operands have swapped position. -static void CommuteVectorShuffleMask(SmallVectorImpl &Mask, MVT VT) { - int NumElems = VT.getVectorNumElements(); - for (int i = 0; i != NumElems; ++i) { - int idx = Mask[i]; - if (idx < 0) +static +SDValue CommuteVectorShuffleMask(SDValue Mask, SelectionDAG &DAG, DebugLoc dl) { + MVT MaskVT = Mask.getValueType(); + MVT EltVT = MaskVT.getVectorElementType(); + unsigned NumElems = Mask.getNumOperands(); + SmallVector MaskVec; + for (unsigned i = 0; i != NumElems; ++i) { + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) { + MaskVec.push_back(DAG.getUNDEF(EltVT)); continue; - else if (idx < NumElems) - Mask[i] = idx + NumElems; + } + assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); + unsigned Val = cast(Arg)->getZExtValue(); + if (Val < NumElems) + MaskVec.push_back(DAG.getConstant(Val + NumElems, EltVT)); else - Mask[i] = idx - NumElems; + MaskVec.push_back(DAG.getConstant(Val - NumElems, EltVT)); } + return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, &MaskVec[0], NumElems); } + /// ShouldXformToMOVHLPS - Return true if the node should be transformed to /// match movhlps. The lower half elements should come from upper half of /// V1 (and in order), and the upper half elements should come from the upper /// half of V2 (and in order). -static bool ShouldXformToMOVHLPS(ShuffleVectorSDNode *Op) { - int NumElems = Op->getValueType(0).getVectorNumElements(); - const int *Mask = Op->getMask(); - +static bool ShouldXformToMOVHLPS(SDNode *Mask) { + unsigned NumElems = Mask->getNumOperands(); if (NumElems != 4) return false; for (unsigned i = 0, e = 2; i != e; ++i) - if (!isUndefOrEqual(Mask[i], i+2)) + if (!isUndefOrEqual(Mask->getOperand(i), i+2)) return false; for (unsigned i = 2; i != 4; ++i) - if (!isUndefOrEqual(Mask[i], i+4)) + if (!isUndefOrEqual(Mask->getOperand(i), i+4)) return false; return true; } @@ -2669,8 +2817,7 @@ /// V1 (and in order), and the upper half elements should come from the upper /// half of V2 (and in order). And since V1 will become the source of the /// MOVLP, it must be either a vector load or a scalar load to vector. -static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2, - ShuffleVectorSDNode *Op) { +static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2, SDNode *Mask) { if (!ISD::isNON_EXTLoad(V1) && !isScalarLoadToVector(V1)) return false; // Is V2 is a vector load, don't do this transformation. We will try to use @@ -2678,16 +2825,14 @@ if (ISD::isNON_EXTLoad(V2)) return false; - int NumElems = Op->getValueType(0).getVectorNumElements(); - const int *Mask = Op->getMask(); - + unsigned NumElems = Mask->getNumOperands(); if (NumElems != 2 && NumElems != 4) return false; - for (int i = 0, e = NumElems/2; i != e; ++i) - if (!isUndefOrEqual(Mask[i], i)) + for (unsigned i = 0, e = NumElems/2; i != e; ++i) + if (!isUndefOrEqual(Mask->getOperand(i), i)) return false; - for (int i = NumElems/2; i != NumElems; ++i) - if (!isUndefOrEqual(Mask[i], i+NumElems)) + for (unsigned i = NumElems/2; i != NumElems; ++i) + if (!isUndefOrEqual(Mask->getOperand(i), i+NumElems)) return false; return true; } @@ -2705,6 +2850,29 @@ return true; } +/// isUndefShuffle - Returns true if N is a VECTOR_SHUFFLE that can be resolved +/// to an undef. +static bool isUndefShuffle(SDNode *N) { + if (N->getOpcode() != ISD::VECTOR_SHUFFLE) + return false; + + SDValue V1 = N->getOperand(0); + SDValue V2 = N->getOperand(1); + SDValue Mask = N->getOperand(2); + unsigned NumElems = Mask.getNumOperands(); + for (unsigned i = 0; i != NumElems; ++i) { + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() != ISD::UNDEF) { + unsigned Val = cast(Arg)->getZExtValue(); + if (Val < NumElems && V1.getOpcode() != ISD::UNDEF) + return false; + else if (Val >= NumElems && V2.getOpcode() != ISD::UNDEF) + return false; + } + } + return true; +} + /// isZeroNode - Returns true if Elt is a constant zero or a floating point /// constant +0.0. static inline bool isZeroNode(SDValue Elt) { @@ -2715,26 +2883,34 @@ } /// isZeroShuffle - Returns true if N is a VECTOR_SHUFFLE that can be resolved -/// to an zero vector. -/// FIXME: move to dag combiner? -static bool isZeroShuffle(ShuffleVectorSDNode *N) { +/// to an zero vector. +static bool isZeroShuffle(SDNode *N) { + if (N->getOpcode() != ISD::VECTOR_SHUFFLE) + return false; + SDValue V1 = N->getOperand(0); SDValue V2 = N->getOperand(1); - const int *Mask = N->getMask(); - int NumElems = N->getValueType(0).getVectorNumElements(); - for (int i = 0; i != NumElems; ++i) { - int Idx = Mask[i]; - if (Idx >= NumElems) { - unsigned Opc = V2.getOpcode(); - if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V2.getNode())) + SDValue Mask = N->getOperand(2); + unsigned NumElems = Mask.getNumOperands(); + for (unsigned i = 0; i != NumElems; ++i) { + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) + continue; + + unsigned Idx = cast(Arg)->getZExtValue(); + if (Idx < NumElems) { + unsigned Opc = V1.getNode()->getOpcode(); + if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V1.getNode())) continue; - if (Opc != ISD::BUILD_VECTOR || !isZeroNode(V2.getOperand(Idx-NumElems))) + if (Opc != ISD::BUILD_VECTOR || + !isZeroNode(V1.getNode()->getOperand(Idx))) return false; - } else if (Idx >= 0) { - unsigned Opc = V1.getOpcode(); - if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V1.getNode())) + } else if (Idx >= NumElems) { + unsigned Opc = V2.getNode()->getOpcode(); + if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V2.getNode())) continue; - if (Opc != ISD::BUILD_VECTOR || !isZeroNode(V1.getOperand(Idx))) + if (Opc != ISD::BUILD_VECTOR || + !isZeroNode(V2.getNode()->getOperand(Idx - NumElems))) return false; } } @@ -2782,94 +2958,127 @@ /// NormalizeMask - V2 is a splat, modify the mask (if needed) so all elements /// that point to V2 points to its first element. -static SDValue NormalizeMask(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { - MVT VT = SVOp->getValueType(0); - int NumElems = VT.getVectorNumElements(); - const int *Mask = SVOp->getMask(); - +static SDValue NormalizeMask(SDValue Mask, SelectionDAG &DAG) { + assert(Mask.getOpcode() == ISD::BUILD_VECTOR); + bool Changed = false; - SmallVector MaskVec; - - for (int i = 0; i != NumElems; ++i) { - int idx = Mask[i]; - if (idx > NumElems) { - idx = NumElems; - Changed = true; + SmallVector MaskVec; + unsigned NumElems = Mask.getNumOperands(); + for (unsigned i = 0; i != NumElems; ++i) { + SDValue Arg = Mask.getOperand(i); + if (Arg.getOpcode() != ISD::UNDEF) { + unsigned Val = cast(Arg)->getZExtValue(); + if (Val > NumElems) { + Arg = DAG.getConstant(NumElems, Arg.getValueType()); + Changed = true; + } } - MaskVec.push_back(idx); + MaskVec.push_back(Arg); } + if (Changed) - return DAG.getVectorShuffle(VT, SVOp->getDebugLoc(), SVOp->getOperand(0), - SVOp->getOperand(1), &MaskVec[0]); - return SDValue(SVOp, 0); + Mask = DAG.getNode(ISD::BUILD_VECTOR, Mask.getDebugLoc(), + Mask.getValueType(), + &MaskVec[0], MaskVec.size()); + return Mask; } /// getMOVLMask - Returns a vector_shuffle mask for an movs{s|d}, movd /// operation of specified width. -static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1, - SDValue V2) { - unsigned NumElems = VT.getVectorNumElements(); - SmallVector Mask; - Mask.push_back(NumElems); +static SDValue getMOVLMask(unsigned NumElems, SelectionDAG &DAG, DebugLoc dl) { + MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); + MVT BaseVT = MaskVT.getVectorElementType(); + + SmallVector MaskVec; + MaskVec.push_back(DAG.getConstant(NumElems, BaseVT)); for (unsigned i = 1; i != NumElems; ++i) - Mask.push_back(i); - return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]); + MaskVec.push_back(DAG.getConstant(i, BaseVT)); + return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskVec[0], MaskVec.size()); } -/// getUnpackl - Returns a vector_shuffle node for an unpackl operation. -static SDValue getUnpackl(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1, - SDValue V2) { - unsigned NumElems = VT.getVectorNumElements(); - SmallVector Mask; +/// getUnpacklMask - Returns a vector_shuffle mask for an unpackl operation +/// of specified width. +static SDValue getUnpacklMask(unsigned NumElems, SelectionDAG &DAG, + DebugLoc dl) { + MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); + MVT BaseVT = MaskVT.getVectorElementType(); + SmallVector MaskVec; for (unsigned i = 0, e = NumElems/2; i != e; ++i) { - Mask.push_back(i); - Mask.push_back(i + NumElems); + MaskVec.push_back(DAG.getConstant(i, BaseVT)); + MaskVec.push_back(DAG.getConstant(i + NumElems, BaseVT)); } - return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]); + return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskVec[0], MaskVec.size()); } -/// getUnpackhMask - Returns a vector_shuffle node for an unpackh operation. -static SDValue getUnpackh(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1, - SDValue V2) { - unsigned NumElems = VT.getVectorNumElements(); +/// getUnpackhMask - Returns a vector_shuffle mask for an unpackh operation +/// of specified width. +static SDValue getUnpackhMask(unsigned NumElems, SelectionDAG &DAG, + DebugLoc dl) { + MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); + MVT BaseVT = MaskVT.getVectorElementType(); unsigned Half = NumElems/2; - SmallVector Mask; + SmallVector MaskVec; for (unsigned i = 0; i != Half; ++i) { - Mask.push_back(i + Half); - Mask.push_back(i + NumElems + Half); + MaskVec.push_back(DAG.getConstant(i + Half, BaseVT)); + MaskVec.push_back(DAG.getConstant(i + NumElems + Half, BaseVT)); } - return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]); + return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskVec[0], MaskVec.size()); +} + +/// getSwapEltZeroMask - Returns a vector_shuffle mask for a shuffle that swaps +/// element #0 of a vector with the specified index, leaving the rest of the +/// elements in place. +static SDValue getSwapEltZeroMask(unsigned NumElems, unsigned DestElt, + SelectionDAG &DAG, DebugLoc dl) { + MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); + MVT BaseVT = MaskVT.getVectorElementType(); + SmallVector MaskVec; + // Element #0 of the result gets the elt we are replacing. + MaskVec.push_back(DAG.getConstant(DestElt, BaseVT)); + for (unsigned i = 1; i != NumElems; ++i) + MaskVec.push_back(DAG.getConstant(i == DestElt ? 0 : i, BaseVT)); + return DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskVec[0], MaskVec.size()); } /// PromoteSplat - Promote a splat of v4f32, v8i16 or v16i8 to v4i32. -static SDValue PromoteSplat(ShuffleVectorSDNode *SV, SelectionDAG &DAG, - bool HasSSE2) { - if (SV->getValueType(0).getVectorNumElements() <= 4) - return SDValue(SV, 0); - - MVT PVT = MVT::v4f32; - MVT VT = SV->getValueType(0); - DebugLoc dl = SV->getDebugLoc(); - SDValue V1 = SV->getOperand(0); - int NumElems = VT.getVectorNumElements(); - int EltNo = SV->getSplatIndex(); - - // unpack elements to the correct location - while (NumElems > 4) { - if (EltNo < NumElems/2) { - V1 = getUnpackl(DAG, dl, VT, V1, V1); - } else { - V1 = getUnpackh(DAG, dl, VT, V1, V1); - EltNo -= NumElems/2; +static SDValue PromoteSplat(SDValue Op, SelectionDAG &DAG, bool HasSSE2) { + MVT PVT = HasSSE2 ? MVT::v4i32 : MVT::v4f32; + MVT VT = Op.getValueType(); + if (PVT == VT) + return Op; + SDValue V1 = Op.getOperand(0); + SDValue Mask = Op.getOperand(2); + unsigned MaskNumElems = Mask.getNumOperands(); + unsigned NumElems = MaskNumElems; + DebugLoc dl = Op.getDebugLoc(); + // Special handling of v4f32 -> v4i32. + if (VT != MVT::v4f32) { + // Find which element we want to splat. + SDNode* EltNoNode = getSplatMaskEltNo(Mask.getNode()).getNode(); + unsigned EltNo = cast(EltNoNode)->getZExtValue(); + // unpack elements to the correct location + while (NumElems > 4) { + if (EltNo < NumElems/2) { + Mask = getUnpacklMask(MaskNumElems, DAG, dl); + } else { + Mask = getUnpackhMask(MaskNumElems, DAG, dl); + EltNo -= NumElems/2; + } + V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V1, Mask); + NumElems >>= 1; } - NumElems >>= 1; + SDValue Cst = DAG.getConstant(EltNo, MVT::i32); + Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Cst, Cst, Cst, Cst); } - - // Perform the splat. - int SplatMask[4] = { EltNo, EltNo, EltNo, EltNo }; + V1 = DAG.getNode(ISD::BIT_CONVERT, dl, PVT, V1); - V1 = DAG.getVectorShuffle(PVT, dl, V1, DAG.getUNDEF(PVT), &SplatMask[0]); - return DAG.getNode(ISD::BIT_CONVERT, dl, VT, V1); + SDValue Shuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, PVT, V1, + DAG.getUNDEF(PVT), Mask); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Shuffle); } /// isVectorLoad - Returns true if the node is a vector load, a scalar @@ -2886,28 +3095,32 @@ /// CanonicalizeMovddup - Cannonicalize movddup shuffle to v2f64. /// -static SDValue CanonicalizeMovddup(ShuffleVectorSDNode *SV, SelectionDAG &DAG, - bool HasSSE3) { +static SDValue CanonicalizeMovddup(SDValue Op, SDValue V1, SDValue Mask, + SelectionDAG &DAG, bool HasSSE3) { // If we have sse3 and shuffle has more than one use or input is a load, then // use movddup. Otherwise, use movlhps. - SDValue V1 = SV->getOperand(0); - - bool UseMovddup = HasSSE3 && (!SV->hasOneUse() || isVectorLoad(V1)); + bool UseMovddup = HasSSE3 && (!Op.hasOneUse() || isVectorLoad(V1)); MVT PVT = UseMovddup ? MVT::v2f64 : MVT::v4f32; - MVT VT = SV->getValueType(0); + MVT VT = Op.getValueType(); if (VT == PVT) - return SDValue(SV, 0); - - DebugLoc dl = SV->getDebugLoc(); - V1 = DAG.getNode(ISD::BIT_CONVERT, dl, PVT, V1); - if (PVT.getVectorNumElements() == 2) { - int Mask[2] = { 0, 0 }; - V1 = DAG.getVectorShuffle(PVT, dl, V1, DAG.getUNDEF(PVT), Mask); + return Op; + DebugLoc dl = Op.getDebugLoc(); + unsigned NumElems = PVT.getVectorNumElements(); + if (NumElems == 2) { + SDValue Cst = DAG.getTargetConstant(0, MVT::i32); + Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i32, Cst, Cst); } else { - int Mask[4] = { 0, 1, 0, 1 }; - V1 = DAG.getVectorShuffle(PVT, dl, V1, DAG.getUNDEF(PVT), Mask); + assert(NumElems == 4); + SDValue Cst0 = DAG.getTargetConstant(0, MVT::i32); + SDValue Cst1 = DAG.getTargetConstant(1, MVT::i32); + Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, + Cst0, Cst1, Cst0, Cst1); } - return DAG.getNode(ISD::BIT_CONVERT, dl, VT, V1); + + V1 = DAG.getNode(ISD::BIT_CONVERT, dl, PVT, V1); + SDValue Shuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, PVT, V1, + DAG.getUNDEF(PVT), Mask); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Shuffle); } /// getShuffleVectorZeroOrUndef - Return a vector_shuffle of the specified @@ -2917,31 +3130,39 @@ static SDValue getShuffleVectorZeroOrUndef(SDValue V2, unsigned Idx, bool isZero, bool HasSSE2, SelectionDAG &DAG) { + DebugLoc dl = V2.getDebugLoc(); MVT VT = V2.getValueType(); SDValue V1 = isZero - ? getZeroVector(VT, HasSSE2, DAG, V2.getDebugLoc()) : DAG.getUNDEF(VT); - unsigned NumElems = VT.getVectorNumElements(); - SmallVector MaskVec; + ? getZeroVector(VT, HasSSE2, DAG, dl) : DAG.getUNDEF(VT); + unsigned NumElems = V2.getValueType().getVectorNumElements(); + MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); + MVT EVT = MaskVT.getVectorElementType(); + SmallVector MaskVec; for (unsigned i = 0; i != NumElems; ++i) - // If this is the insertion idx, put the low elt of V2 here. - MaskVec.push_back(i == Idx ? NumElems : i); - return DAG.getVectorShuffle(VT, V2.getDebugLoc(), V1, V2, &MaskVec[0]); + if (i == Idx) // If this is the insertion idx, put the low elt of V2 here. + MaskVec.push_back(DAG.getConstant(NumElems, EVT)); + else + MaskVec.push_back(DAG.getConstant(i, EVT)); + SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskVec[0], MaskVec.size()); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, Mask); } /// getNumOfConsecutiveZeros - Return the number of elements in a result of /// a shuffle that is zero. static -unsigned getNumOfConsecutiveZeros(ShuffleVectorSDNode *SVOp, const int *Mask, - int NumElems, bool Low, SelectionDAG &DAG) { +unsigned getNumOfConsecutiveZeros(SDValue Op, SDValue Mask, + unsigned NumElems, bool Low, + SelectionDAG &DAG) { unsigned NumZeros = 0; - for (int i = 0; i < NumElems; ++i) { + for (unsigned i = 0; i < NumElems; ++i) { unsigned Index = Low ? i : NumElems-i-1; - int Idx = Mask[Index]; - if (Idx < 0) { + SDValue Idx = Mask.getOperand(Index); + if (Idx.getOpcode() == ISD::UNDEF) { ++NumZeros; continue; } - SDValue Elt = DAG.getShuffleScalarElt(SVOp, Index); + SDValue Elt = DAG.getShuffleScalarElt(Op.getNode(), Index); if (Elt.getNode() && isZeroNode(Elt)) ++NumZeros; else @@ -2952,40 +3173,40 @@ /// isVectorShift - Returns true if the shuffle can be implemented as a /// logical left or right shift of a vector. -/// FIXME: split into pslldqi, psrldqi, palignr variants. -static bool isVectorShift(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG, +static bool isVectorShift(SDValue Op, SDValue Mask, SelectionDAG &DAG, bool &isLeft, SDValue &ShVal, unsigned &ShAmt) { - const int *Mask = SVOp->getMask(); - int NumElems = SVOp->getValueType(0).getVectorNumElements(); + unsigned NumElems = Mask.getNumOperands(); isLeft = true; - unsigned NumZeros = getNumOfConsecutiveZeros(SVOp, Mask, NumElems, true, DAG); + unsigned NumZeros= getNumOfConsecutiveZeros(Op, Mask, NumElems, true, DAG); if (!NumZeros) { isLeft = false; - NumZeros = getNumOfConsecutiveZeros(SVOp, Mask, NumElems, false, DAG); + NumZeros = getNumOfConsecutiveZeros(Op, Mask, NumElems, false, DAG); if (!NumZeros) return false; } + bool SeenV1 = false; bool SeenV2 = false; - for (int i = NumZeros; i < NumElems; ++i) { - int Val = isLeft ? (i - NumZeros) : i; - int Idx = Mask[isLeft ? i : (i - NumZeros)]; - if (Idx < 0) + for (unsigned i = NumZeros; i < NumElems; ++i) { + unsigned Val = isLeft ? (i - NumZeros) : i; + SDValue Idx = Mask.getOperand(isLeft ? i : (i - NumZeros)); + if (Idx.getOpcode() == ISD::UNDEF) continue; - if (Idx < NumElems) + unsigned Index = cast(Idx)->getZExtValue(); + if (Index < NumElems) SeenV1 = true; else { - Idx -= NumElems; + Index -= NumElems; SeenV2 = true; } - if (Idx != Val) + if (Index != Val) return false; } if (SeenV1 && SeenV2) return false; - ShVal = SeenV1 ? SVOp->getOperand(0) : SVOp->getOperand(1); + ShVal = SeenV1 ? Op.getOperand(0) : Op.getOperand(1); ShAmt = NumZeros; return true; } @@ -3070,8 +3291,8 @@ /// getVShift - Return a vector logical shift node. /// static SDValue getVShift(bool isLeft, MVT VT, SDValue SrcOp, - unsigned NumBits, SelectionDAG &DAG, - const TargetLowering &TLI, DebugLoc dl) { + unsigned NumBits, SelectionDAG &DAG, + const TargetLowering &TLI, DebugLoc dl) { bool isMMX = VT.getSizeInBits() == 64; MVT ShVT = isMMX ? MVT::v1i64 : MVT::v2i64; unsigned Opc = isLeft ? X86ISD::VSHL : X86ISD::VSRL; @@ -3156,13 +3377,11 @@ // Now we have our 32-bit value zero extended in the low element of // a vector. If Idx != 0, swizzle it into place. if (Idx != 0) { - SmallVector Mask; - Mask.push_back(Idx); - for (unsigned i = 1; i != VecElts; ++i) - Mask.push_back(i); - Item = DAG.getVectorShuffle(VecVT, dl, Item, - DAG.getUNDEF(Item.getValueType()), - &Mask[0]); + SDValue Ops[] = { + Item, DAG.getUNDEF(Item.getValueType()), + getSwapEltZeroMask(VecElts, Idx, DAG, dl) + }; + Item = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VecVT, Ops, 3); } return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Item); } @@ -3206,10 +3425,15 @@ // Turn it into a shuffle of zero and zero-extended scalar to vector. Item = getShuffleVectorZeroOrUndef(Item, 0, NumZero > 0, Subtarget->hasSSE2(), DAG); - SmallVector MaskVec; + MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); + MVT MaskEVT = MaskVT.getVectorElementType(); + SmallVector MaskVec; for (unsigned i = 0; i < NumElems; i++) - MaskVec.push_back(i == Idx ? 0 : 1); - return DAG.getVectorShuffle(VT, dl, Item, DAG.getUNDEF(VT), &MaskVec[0]); + MaskVec.push_back(DAG.getConstant((i == Idx) ? 0 : 1, MaskEVT)); + SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskVec[0], MaskVec.size()); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, Item, + DAG.getUNDEF(VT), Mask); } } @@ -3267,48 +3491,54 @@ V[i] = V[i*2]; // Must be a zero vector. break; case 1: - V[i] = getMOVL(DAG, dl, VT, V[i*2+1], V[i*2]); + V[i] = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[i*2+1], V[i*2], + getMOVLMask(NumElems, DAG, dl)); break; case 2: - V[i] = getMOVL(DAG, dl, VT, V[i*2], V[i*2+1]); + V[i] = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[i*2], V[i*2+1], + getMOVLMask(NumElems, DAG, dl)); break; case 3: - V[i] = getUnpackl(DAG, dl, VT, V[i*2], V[i*2+1]); + V[i] = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[i*2], V[i*2+1], + getUnpacklMask(NumElems, DAG, dl)); break; } } - SmallVector MaskVec; + MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); + MVT EVT = MaskVT.getVectorElementType(); + SmallVector MaskVec; bool Reverse = (NonZeros & 0x3) == 2; for (unsigned i = 0; i < 2; ++i) - MaskVec.push_back(Reverse ? 1-i : i); + if (Reverse) + MaskVec.push_back(DAG.getConstant(1-i, EVT)); + else + MaskVec.push_back(DAG.getConstant(i, EVT)); Reverse = ((NonZeros & (0x3 << 2)) >> 2) == 2; for (unsigned i = 0; i < 2; ++i) - MaskVec.push_back(Reverse ? 1-i+NumElems : i+NumElems); - return DAG.getVectorShuffle(VT, dl, V[0], V[1], &MaskVec[0]); + if (Reverse) + MaskVec.push_back(DAG.getConstant(1-i+NumElems, EVT)); + else + MaskVec.push_back(DAG.getConstant(i+NumElems, EVT)); + SDValue ShufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskVec[0], MaskVec.size()); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[0], V[1], ShufMask); } if (Values.size() > 2) { - // If we have SSE 4.1, Expand into a number of inserts. - if (getSubtarget()->hasSSE41()) { - V[0] = DAG.getUNDEF(VT); - for (unsigned i = 0; i < NumElems; ++i) - if (Op.getOperand(i).getOpcode() != ISD::UNDEF) - V[0] = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, VT, V[0], - Op.getOperand(i), DAG.getIntPtrConstant(i)); - return V[0]; - } // Expand into a number of unpckl*. // e.g. for v4f32 // Step 1: unpcklps 0, 2 ==> X: // : unpcklps 1, 3 ==> Y: // Step 2: unpcklps X, Y ==> <3, 2, 1, 0> + SDValue UnpckMask = getUnpacklMask(NumElems, DAG, dl); for (unsigned i = 0; i < NumElems; ++i) V[i] = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Op.getOperand(i)); NumElems >>= 1; while (NumElems != 0) { for (unsigned i = 0; i < NumElems; ++i) - V[i] = getUnpackl(DAG, dl, VT, V[i], V[i + NumElems]); + V[i] = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V[i], V[i + NumElems], + UnpckMask); NumElems >>= 1; } return V[0]; @@ -3323,12 +3553,11 @@ // 3. [ssse3] 2 x pshufb + 1 x por // 4. [all] mov + pshuflw + pshufhw + N x (pextrw + pinsrw) static -SDValue LowerVECTOR_SHUFFLEv8i16(ShuffleVectorSDNode *SVOp, - SelectionDAG &DAG, X86TargetLowering &TLI) { - SDValue V1 = SVOp->getOperand(0); - SDValue V2 = SVOp->getOperand(1); - DebugLoc dl = SVOp->getDebugLoc(); - const int *Mask = SVOp->getMask(); +SDValue LowerVECTOR_SHUFFLEv8i16(SDValue V1, SDValue V2, + SDValue PermMask, SelectionDAG &DAG, + X86TargetLowering &TLI, DebugLoc dl) { + SmallVector MaskElts(PermMask.getNode()->op_begin(), + PermMask.getNode()->op_end()); SmallVector MaskVals; // Determine if more than 1 of the words in each of the low and high quadwords @@ -3339,7 +3568,9 @@ BitVector InputQuads(4); for (unsigned i = 0; i < 8; ++i) { SmallVectorImpl &Quad = i < 4 ? LoQuad : HiQuad; - int EltIdx = Mask[i]; + SDValue Elt = MaskElts[i]; + int EltIdx = Elt.getOpcode() == ISD::UNDEF ? -1 : + cast(Elt)->getZExtValue(); MaskVals.push_back(EltIdx); if (EltIdx < 0) { ++Quad[0]; @@ -3392,12 +3623,14 @@ // words from all 4 input quadwords. SDValue NewV; if (BestLoQuad >= 0 || BestHiQuad >= 0) { - SmallVector MaskV; - MaskV.push_back(BestLoQuad < 0 ? 0 : BestLoQuad); - MaskV.push_back(BestHiQuad < 0 ? 1 : BestHiQuad); - NewV = DAG.getVectorShuffle(MVT::v2i64, dl, - DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V1), - DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V2), &MaskV[0]); + SmallVector MaskV; + MaskV.push_back(DAG.getConstant(BestLoQuad < 0 ? 0 : BestLoQuad, MVT::i64)); + MaskV.push_back(DAG.getConstant(BestHiQuad < 0 ? 1 : BestHiQuad, MVT::i64)); + SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64, &MaskV[0], 2); + + NewV = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v2i64, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V1), + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V2), Mask); NewV = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, NewV); // Rewrite the MaskVals and assign NewV to V1 if NewV now contains all the @@ -3435,8 +3668,15 @@ // If we've eliminated the use of V2, and the new mask is a pshuflw or // pshufhw, that's as cheap as it gets. Return the new shuffle. if ((pshufhw && InOrder[0]) || (pshuflw && InOrder[1])) { - return DAG.getVectorShuffle(MVT::v8i16, dl, NewV, - DAG.getUNDEF(MVT::v8i16), &MaskVals[0]); + MaskV.clear(); + for (unsigned i = 0; i != 8; ++i) + MaskV.push_back((MaskVals[i] < 0) ? DAG.getUNDEF(MVT::i16) + : DAG.getConstant(MaskVals[i], + MVT::i16)); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v8i16, NewV, + DAG.getUNDEF(MVT::v8i16), + DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v8i16, + &MaskV[0], 8)); } } @@ -3493,45 +3733,49 @@ // and update MaskVals with new element order. BitVector InOrder(8); if (BestLoQuad >= 0) { - SmallVector MaskV; + SmallVector MaskV; for (int i = 0; i != 4; ++i) { int idx = MaskVals[i]; if (idx < 0) { - MaskV.push_back(-1); + MaskV.push_back(DAG.getUNDEF(MVT::i16)); InOrder.set(i); } else if ((idx / 4) == BestLoQuad) { - MaskV.push_back(idx & 3); + MaskV.push_back(DAG.getConstant(idx & 3, MVT::i16)); InOrder.set(i); } else { - MaskV.push_back(-1); + MaskV.push_back(DAG.getUNDEF(MVT::i16)); } } for (unsigned i = 4; i != 8; ++i) - MaskV.push_back(i); - NewV = DAG.getVectorShuffle(MVT::v8i16, dl, NewV, DAG.getUNDEF(MVT::v8i16), - &MaskV[0]); + MaskV.push_back(DAG.getConstant(i, MVT::i16)); + NewV = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v8i16, NewV, + DAG.getUNDEF(MVT::v8i16), + DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::v8i16, &MaskV[0], 8)); } // If BestHi >= 0, generate a pshufhw to put the high elements in order, // and update MaskVals with the new element order. if (BestHiQuad >= 0) { - SmallVector MaskV; + SmallVector MaskV; for (unsigned i = 0; i != 4; ++i) - MaskV.push_back(i); + MaskV.push_back(DAG.getConstant(i, MVT::i16)); for (unsigned i = 4; i != 8; ++i) { int idx = MaskVals[i]; if (idx < 0) { - MaskV.push_back(-1); + MaskV.push_back(DAG.getUNDEF(MVT::i16)); InOrder.set(i); } else if ((idx / 4) == BestHiQuad) { - MaskV.push_back((idx & 3) + 4); + MaskV.push_back(DAG.getConstant((idx & 3) + 4, MVT::i16)); InOrder.set(i); } else { - MaskV.push_back(-1); + MaskV.push_back(DAG.getUNDEF(MVT::i16)); } } - NewV = DAG.getVectorShuffle(MVT::v8i16, dl, NewV, DAG.getUNDEF(MVT::v8i16), - &MaskV[0]); + NewV = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v8i16, NewV, + DAG.getUNDEF(MVT::v8i16), + DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::v8i16, &MaskV[0], 8)); } // In case BestHi & BestLo were both -1, which means each quadword has a word @@ -3567,12 +3811,11 @@ // 2. [ssse3] 2 x pshufb + 1 x por // 3. [all] v8i16 shuffle + N x pextrw + rotate + pinsrw static -SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp, - SelectionDAG &DAG, X86TargetLowering &TLI) { - SDValue V1 = SVOp->getOperand(0); - SDValue V2 = SVOp->getOperand(1); - DebugLoc dl = SVOp->getDebugLoc(); - const int *Mask = SVOp->getMask(); +SDValue LowerVECTOR_SHUFFLEv16i8(SDValue V1, SDValue V2, + SDValue PermMask, SelectionDAG &DAG, + X86TargetLowering &TLI, DebugLoc dl) { + SmallVector MaskElts(PermMask.getNode()->op_begin(), + PermMask.getNode()->op_end()); SmallVector MaskVals; // If we have SSSE3, case 1 is generated when all result bytes come from @@ -3582,7 +3825,9 @@ bool V1Only = true; bool V2Only = true; for (unsigned i = 0; i < 16; ++i) { - int EltIdx = Mask[i]; + SDValue Elt = MaskElts[i]; + int EltIdx = Elt.getOpcode() == ISD::UNDEF ? -1 : + cast(Elt)->getZExtValue(); MaskVals.push_back(EltIdx); if (EltIdx < 0) continue; @@ -3713,14 +3958,11 @@ /// the right sequence. e.g. /// vector_shuffle <>, <>, < 3, 4, | 10, 11, | 0, 1, | 14, 15> static -SDValue RewriteAsNarrowerShuffle(ShuffleVectorSDNode *SVOp, - SelectionDAG &DAG, - TargetLowering &TLI, DebugLoc dl) { - MVT VT = SVOp->getValueType(0); - SDValue V1 = SVOp->getOperand(0); - SDValue V2 = SVOp->getOperand(1); - const int *PermMask = SVOp->getMask(); - unsigned NumElems = VT.getVectorNumElements(); +SDValue RewriteAsNarrowerShuffle(SDValue V1, SDValue V2, + MVT VT, + SDValue PermMask, SelectionDAG &DAG, + TargetLowering &TLI, DebugLoc dl) { + unsigned NumElems = PermMask.getNumOperands(); unsigned NewWidth = (NumElems == 4) ? 2 : 4; MVT MaskVT = MVT::getIntVectorWithNumElements(NewWidth); MVT MaskEltVT = MaskVT.getVectorElementType(); @@ -3739,35 +3981,38 @@ else NewVT = MVT::v2f64; } - int Scale = NumElems / NewWidth; - SmallVector MaskVec; + unsigned Scale = NumElems / NewWidth; + SmallVector MaskVec; for (unsigned i = 0; i < NumElems; i += Scale) { - int StartIdx = -1; - for (int j = 0; j < Scale; ++j) { - int EltIdx = PermMask[i+j]; - if (EltIdx < 0) + unsigned StartIdx = ~0U; + for (unsigned j = 0; j < Scale; ++j) { + SDValue Elt = PermMask.getOperand(i+j); + if (Elt.getOpcode() == ISD::UNDEF) continue; - if (StartIdx == -1) + unsigned EltIdx = cast(Elt)->getZExtValue(); + if (StartIdx == ~0U) StartIdx = EltIdx - (EltIdx % Scale); if (EltIdx != StartIdx + j) return SDValue(); } - if (StartIdx == -1) - MaskVec.push_back(-1); + if (StartIdx == ~0U) + MaskVec.push_back(DAG.getUNDEF(MaskEltVT)); else - MaskVec.push_back(StartIdx / Scale); + MaskVec.push_back(DAG.getConstant(StartIdx / Scale, MaskEltVT)); } V1 = DAG.getNode(ISD::BIT_CONVERT, dl, NewVT, V1); V2 = DAG.getNode(ISD::BIT_CONVERT, dl, NewVT, V2); - return DAG.getVectorShuffle(NewVT, dl, V1, V2, &MaskVec[0]); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, NewVT, V1, V2, + DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskVec[0], MaskVec.size())); } /// getVZextMovL - Return a zero-extending vector move low node. /// static SDValue getVZextMovL(MVT VT, MVT OpVT, - SDValue SrcOp, SelectionDAG &DAG, - const X86Subtarget *Subtarget, DebugLoc dl) { + SDValue SrcOp, SelectionDAG &DAG, + const X86Subtarget *Subtarget, DebugLoc dl) { if (VT == MVT::v2f64 || VT == MVT::v4f32) { LoadSDNode *LD = NULL; if (!isScalarLoadToVector(SrcOp.getNode(), &LD)) @@ -3801,37 +4046,31 @@ /// LowerVECTOR_SHUFFLE_4wide - Handle all 4 wide cases with a number of /// shuffles. static SDValue -LowerVECTOR_SHUFFLE_4wide(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { - SDValue V1 = SVOp->getOperand(0); - SDValue V2 = SVOp->getOperand(1); - DebugLoc dl = SVOp->getDebugLoc(); - MVT VT = SVOp->getValueType(0); - const int *PermMaskPtr = SVOp->getMask(); - +LowerVECTOR_SHUFFLE_4wide(SDValue V1, SDValue V2, + SDValue PermMask, MVT VT, SelectionDAG &DAG, + DebugLoc dl) { + MVT MaskVT = PermMask.getValueType(); + MVT MaskEVT = MaskVT.getVectorElementType(); SmallVector, 8> Locs; Locs.resize(4); - SmallVector Mask1(4U, -1); - SmallVector PermMask; - - for (unsigned i = 0; i != 8; ++i) - PermMask.push_back(PermMaskPtr[i]); - + SmallVector Mask1(4, DAG.getUNDEF(MaskEVT)); unsigned NumHi = 0; unsigned NumLo = 0; for (unsigned i = 0; i != 4; ++i) { - int Idx = PermMask[i]; - if (Idx < 0) { + SDValue Elt = PermMask.getOperand(i); + if (Elt.getOpcode() == ISD::UNDEF) { Locs[i] = std::make_pair(-1, -1); } else { - assert(Idx < 8 && "Invalid VECTOR_SHUFFLE index!"); - if (Idx < 4) { + unsigned Val = cast(Elt)->getZExtValue(); + assert(Val < 8 && "Invalid VECTOR_SHUFFLE index!"); + if (Val < 4) { Locs[i] = std::make_pair(0, NumLo); - Mask1[NumLo] = Idx; + Mask1[NumLo] = Elt; NumLo++; } else { Locs[i] = std::make_pair(1, NumHi); if (2+NumHi < 4) - Mask1[2+NumHi] = Idx; + Mask1[2+NumHi] = Elt; NumHi++; } } @@ -3842,21 +4081,24 @@ // implemented with two shuffles. First shuffle gather the elements. // The second shuffle, which takes the first shuffle as both of its // vector operands, put the elements into the right order. - V1 = DAG.getVectorShuffle(VT, dl, V1, V2, &Mask1[0]); + V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, + DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &Mask1[0], Mask1.size())); - SmallVector Mask2(4U, -1); - + SmallVector Mask2(4, DAG.getUNDEF(MaskEVT)); for (unsigned i = 0; i != 4; ++i) { if (Locs[i].first == -1) continue; else { unsigned Idx = (i < 2) ? 0 : 4; Idx += Locs[i].first * 2 + Locs[i].second; - Mask2[i] = Idx; + Mask2[i] = DAG.getConstant(Idx, MaskEVT); } } - return DAG.getVectorShuffle(VT, dl, V1, V1, &Mask2[0]); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V1, + DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &Mask2[0], Mask2.size())); } else if (NumLo == 3 || NumHi == 3) { // Otherwise, we must have three elements from one vector, call it X, and // one element from the other, call it Y. First, use a shufps to build an @@ -3867,51 +4109,60 @@ // from X. if (NumHi == 3) { // Normalize it so the 3 elements come from V1. - CommuteVectorShuffleMask(PermMask, VT); + PermMask = CommuteVectorShuffleMask(PermMask, DAG, dl); std::swap(V1, V2); } // Find the element from V2. unsigned HiIndex; for (HiIndex = 0; HiIndex < 3; ++HiIndex) { - int Val = PermMask[HiIndex]; - if (Val < 0) + SDValue Elt = PermMask.getOperand(HiIndex); + if (Elt.getOpcode() == ISD::UNDEF) continue; + unsigned Val = cast(Elt)->getZExtValue(); if (Val >= 4) break; } - Mask1[0] = PermMask[HiIndex]; - Mask1[1] = -1; - Mask1[2] = PermMask[HiIndex^1]; - Mask1[3] = -1; - V2 = DAG.getVectorShuffle(VT, dl, V1, V2, &Mask1[0]); + Mask1[0] = PermMask.getOperand(HiIndex); + Mask1[1] = DAG.getUNDEF(MaskEVT); + Mask1[2] = PermMask.getOperand(HiIndex^1); + Mask1[3] = DAG.getUNDEF(MaskEVT); + V2 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, + DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, &Mask1[0], 4)); if (HiIndex >= 2) { - Mask1[0] = PermMask[0]; - Mask1[1] = PermMask[1]; - Mask1[2] = HiIndex & 1 ? 6 : 4; - Mask1[3] = HiIndex & 1 ? 4 : 6; - return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask1[0]); + Mask1[0] = PermMask.getOperand(0); + Mask1[1] = PermMask.getOperand(1); + Mask1[2] = DAG.getConstant(HiIndex & 1 ? 6 : 4, MaskEVT); + Mask1[3] = DAG.getConstant(HiIndex & 1 ? 4 : 6, MaskEVT); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, + DAG.getNode(ISD::BUILD_VECTOR, dl, + MaskVT, &Mask1[0], 4)); } else { - Mask1[0] = HiIndex & 1 ? 2 : 0; - Mask1[1] = HiIndex & 1 ? 0 : 2; - Mask1[2] = PermMask[2]; - Mask1[3] = PermMask[3]; - if (Mask1[2] >= 0) - Mask1[2] += 4; - if (Mask1[3] >= 0) - Mask1[3] += 4; - return DAG.getVectorShuffle(VT, dl, V2, V1, &Mask1[0]); + Mask1[0] = DAG.getConstant(HiIndex & 1 ? 2 : 0, MaskEVT); + Mask1[1] = DAG.getConstant(HiIndex & 1 ? 0 : 2, MaskEVT); + Mask1[2] = PermMask.getOperand(2); + Mask1[3] = PermMask.getOperand(3); + if (Mask1[2].getOpcode() != ISD::UNDEF) + Mask1[2] = + DAG.getConstant(cast(Mask1[2])->getZExtValue()+4, + MaskEVT); + if (Mask1[3].getOpcode() != ISD::UNDEF) + Mask1[3] = + DAG.getConstant(cast(Mask1[3])->getZExtValue()+4, + MaskEVT); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V2, V1, + DAG.getNode(ISD::BUILD_VECTOR, dl, + MaskVT, &Mask1[0], 4)); } } // Break it into (shuffle shuffle_hi, shuffle_lo). Locs.clear(); - SmallVector LoMask(4U, -1); - SmallVector HiMask(4U, -1); - - SmallVector *MaskPtr = &LoMask; + SmallVector LoMask(4, DAG.getUNDEF(MaskEVT)); + SmallVector HiMask(4, DAG.getUNDEF(MaskEVT)); + SmallVector *MaskPtr = &LoMask; unsigned MaskIdx = 0; unsigned LoIdx = 0; unsigned HiIdx = 2; @@ -3922,68 +4173,84 @@ LoIdx = 0; HiIdx = 2; } - int Idx = PermMask[i]; - if (Idx < 0) { + SDValue Elt = PermMask.getOperand(i); + if (Elt.getOpcode() == ISD::UNDEF) { Locs[i] = std::make_pair(-1, -1); - } else if (Idx < 4) { + } else if (cast(Elt)->getZExtValue() < 4) { Locs[i] = std::make_pair(MaskIdx, LoIdx); - (*MaskPtr)[LoIdx] = Idx; + (*MaskPtr)[LoIdx] = Elt; LoIdx++; } else { Locs[i] = std::make_pair(MaskIdx, HiIdx); - (*MaskPtr)[HiIdx] = Idx; + (*MaskPtr)[HiIdx] = Elt; HiIdx++; } } - SDValue LoShuffle = DAG.getVectorShuffle(VT, dl, V1, V2, &LoMask[0]); - SDValue HiShuffle = DAG.getVectorShuffle(VT, dl, V1, V2, &HiMask[0]); - SmallVector MaskOps; + SDValue LoShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, + DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &LoMask[0], LoMask.size())); + SDValue HiShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, + DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &HiMask[0], HiMask.size())); + SmallVector MaskOps; for (unsigned i = 0; i != 4; ++i) { if (Locs[i].first == -1) { - MaskOps.push_back(-1); + MaskOps.push_back(DAG.getUNDEF(MaskEVT)); } else { unsigned Idx = Locs[i].first * 4 + Locs[i].second; - MaskOps.push_back(Idx); + MaskOps.push_back(DAG.getConstant(Idx, MaskEVT)); } } - return DAG.getVectorShuffle(VT, dl, LoShuffle, HiShuffle, &MaskOps[0]); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, LoShuffle, HiShuffle, + DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &MaskOps[0], MaskOps.size())); } SDValue X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { - ShuffleVectorSDNode *SVOp = cast(Op); SDValue V1 = Op.getOperand(0); SDValue V2 = Op.getOperand(1); + SDValue PermMask = Op.getOperand(2); MVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); - const int *PermMask = cast(Op.getNode())->getMask(); - unsigned NumElems = VT.getVectorNumElements(); + unsigned NumElems = PermMask.getNumOperands(); bool isMMX = VT.getSizeInBits() == 64; bool V1IsUndef = V1.getOpcode() == ISD::UNDEF; bool V2IsUndef = V2.getOpcode() == ISD::UNDEF; bool V1IsSplat = false; bool V2IsSplat = false; - if (isZeroShuffle(SVOp)) + // FIXME: Check for legal shuffle and return? + + if (isUndefShuffle(Op.getNode())) + return DAG.getUNDEF(VT); + + if (isZeroShuffle(Op.getNode())) return getZeroVector(VT, Subtarget->hasSSE2(), DAG, dl); + if (isIdentityMask(PermMask.getNode())) + return V1; + else if (isIdentityMask(PermMask.getNode(), true)) + return V2; + // Canonicalize movddup shuffles. - if (V2IsUndef && Subtarget->hasSSE2() && VT.getSizeInBits() == 128 && - X86::isMOVDDUPMask(SVOp)) - return CanonicalizeMovddup(SVOp, DAG, Subtarget->hasSSE3()); - - // Promote splats to v4f32. - if (SVOp->isSplat()) { - if (isMMX || NumElems < 4) - return Op; - return PromoteSplat(SVOp, DAG, Subtarget->hasSSE2()); + if (V2IsUndef && Subtarget->hasSSE2() && + VT.getSizeInBits() == 128 && + X86::isMOVDDUPMask(PermMask.getNode())) + return CanonicalizeMovddup(Op, V1, PermMask, DAG, Subtarget->hasSSE3()); + + if (isSplatMask(PermMask.getNode())) { + if (isMMX || NumElems < 4) return Op; + // Promote it to a v4{if}32 splat. + return PromoteSplat(Op, DAG, Subtarget->hasSSE2()); } // If the shuffle can be profitably rewritten as a narrower shuffle, then // do it! if (VT == MVT::v8i16 || VT == MVT::v16i8) { - SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, *this, dl); + SDValue NewOp= RewriteAsNarrowerShuffle(V1, V2, VT, PermMask, DAG, + *this, dl); if (NewOp.getNode()) return DAG.getNode(ISD::BIT_CONVERT, dl, VT, LowerVECTOR_SHUFFLE(NewOp, DAG)); @@ -3991,29 +4258,32 @@ // FIXME: Figure out a cleaner way to do this. // Try to make use of movq to zero out the top part. if (ISD::isBuildVectorAllZeros(V2.getNode())) { - SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, *this, dl); + SDValue NewOp = RewriteAsNarrowerShuffle(V1, V2, VT, PermMask, + DAG, *this, dl); if (NewOp.getNode()) { - if (isCommutedMOVL(cast(NewOp), true, false)) - return getVZextMovL(VT, NewOp.getValueType(), NewOp.getOperand(0), - DAG, Subtarget, dl); + SDValue NewV1 = NewOp.getOperand(0); + SDValue NewV2 = NewOp.getOperand(1); + SDValue NewMask = NewOp.getOperand(2); + if (isCommutedMOVL(NewMask.getNode(), true, false)) { + NewOp = CommuteVectorShuffle(NewOp, NewV1, NewV2, NewMask, DAG); + return getVZextMovL(VT, NewOp.getValueType(), NewV2, DAG, Subtarget, + dl); + } } } else if (ISD::isBuildVectorAllZeros(V1.getNode())) { - SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, *this, dl); - if (NewOp.getNode() && X86::isMOVLMask(cast(NewOp))) + SDValue NewOp= RewriteAsNarrowerShuffle(V1, V2, VT, PermMask, + DAG, *this, dl); + if (NewOp.getNode() && X86::isMOVLMask(NewOp.getOperand(2).getNode())) return getVZextMovL(VT, NewOp.getValueType(), NewOp.getOperand(1), - DAG, Subtarget, dl); + DAG, Subtarget, dl); } } - - if (X86::isPSHUFDMask(SVOp)) - return Op; - + // Check if this can be converted into a logical shift. bool isLeft = false; unsigned ShAmt = 0; SDValue ShVal; - bool isShift = getSubtarget()->hasSSE2() && - isVectorShift(SVOp, DAG, isLeft, ShVal, ShAmt); + bool isShift = isVectorShift(Op, PermMask, DAG, isLeft, ShVal, ShAmt); if (isShift && ShVal.hasOneUse()) { // If the shifted value has multiple uses, it may be cheaper to use // v_set0 + movlhps or movhlps, etc. @@ -4021,8 +4291,8 @@ ShAmt *= EVT.getSizeInBits(); return getVShift(isLeft, VT, ShVal, ShAmt, DAG, *this, dl); } - - if (X86::isMOVLMask(SVOp)) { + + if (X86::isMOVLMask(PermMask.getNode())) { if (V1IsUndef) return V2; if (ISD::isBuildVectorAllZeros(V1.getNode())) @@ -4030,18 +4300,17 @@ if (!isMMX) return Op; } - - // FIXME: fold these into legal mask. - if (!isMMX && (X86::isMOVSHDUPMask(SVOp) || - X86::isMOVSLDUPMask(SVOp) || - X86::isMOVHLPSMask(SVOp) || - X86::isMOVHPMask(SVOp) || - X86::isMOVLPMask(SVOp))) + + if (!isMMX && (X86::isMOVSHDUPMask(PermMask.getNode()) || + X86::isMOVSLDUPMask(PermMask.getNode()) || + X86::isMOVHLPSMask(PermMask.getNode()) || + X86::isMOVHPMask(PermMask.getNode()) || + X86::isMOVLPMask(PermMask.getNode()))) return Op; - if (ShouldXformToMOVHLPS(SVOp) || - ShouldXformToMOVLP(V1.getNode(), V2.getNode(), SVOp)) - return CommuteVectorShuffle(SVOp, DAG); + if (ShouldXformToMOVHLPS(PermMask.getNode()) || + ShouldXformToMOVLP(V1.getNode(), V2.getNode(), PermMask.getNode())) + return CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); if (isShift) { // No better options. Use a vshl / vsrl. @@ -4049,7 +4318,7 @@ ShAmt *= EVT.getSizeInBits(); return getVShift(isLeft, VT, ShVal, ShAmt, DAG, *this, dl); } - + bool Commuted = false; // FIXME: This should also accept a bitcast of a splat? Be careful, not // 1,1,1,1 -> v8i16 though. @@ -4058,84 +4327,115 @@ // Canonicalize the splat or undef, if present, to be on the RHS. if ((V1IsSplat || V1IsUndef) && !(V2IsSplat || V2IsUndef)) { - Op = CommuteVectorShuffle(SVOp, DAG); - SVOp = cast(Op); - V1 = SVOp->getOperand(0); - V2 = SVOp->getOperand(1); + Op = CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); std::swap(V1IsSplat, V2IsSplat); std::swap(V1IsUndef, V2IsUndef); Commuted = true; } - if (isCommutedMOVL(SVOp, V2IsSplat, V2IsUndef)) { - // Shuffling low element of v1 into undef, just return v1. - if (V2IsUndef) - return V1; - // If V2 is a splat, the mask may be malformed such as <4,3,3,3>, which - // the instruction selector will not match, so get a canonical MOVL with - // swapped operands to undo the commute. - return getMOVL(DAG, dl, VT, V2, V1); + // FIXME: Figure out a cleaner way to do this. + if (isCommutedMOVL(PermMask.getNode(), V2IsSplat, V2IsUndef)) { + if (V2IsUndef) return V1; + Op = CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); + if (V2IsSplat) { + // V2 is a splat, so the mask may be malformed. That is, it may point + // to any V2 element. The instruction selectior won't like this. Get + // a corrected mask and commute to form a proper MOVS{S|D}. + SDValue NewMask = getMOVLMask(NumElems, DAG, dl); + if (NewMask.getNode() != PermMask.getNode()) + Op = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, NewMask); + } + return Op; } - if (X86::isUNPCKL_v_undef_Mask(SVOp) || - X86::isUNPCKH_v_undef_Mask(SVOp) || - X86::isUNPCKLMask(SVOp) || - X86::isUNPCKHMask(SVOp)) + if (X86::isUNPCKL_v_undef_Mask(PermMask.getNode()) || + X86::isUNPCKH_v_undef_Mask(PermMask.getNode()) || + X86::isUNPCKLMask(PermMask.getNode()) || + X86::isUNPCKHMask(PermMask.getNode())) return Op; if (V2IsSplat) { // Normalize mask so all entries that point to V2 points to its first // element then try to match unpck{h|l} again. If match, return a // new vector_shuffle with the corrected mask. - SDValue NewMask = NormalizeMask(SVOp, DAG); - ShuffleVectorSDNode *NSVOp = cast(NewMask); - if (NSVOp != SVOp) { - if (X86::isUNPCKLMask(NSVOp, true)) { - return NewMask; - } else if (X86::isUNPCKHMask(NSVOp, true)) { - return NewMask; + SDValue NewMask = NormalizeMask(PermMask, DAG); + if (NewMask.getNode() != PermMask.getNode()) { + if (X86::isUNPCKLMask(NewMask.getNode(), true)) { + SDValue NewMask = getUnpacklMask(NumElems, DAG, dl); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, NewMask); + } else if (X86::isUNPCKHMask(NewMask.getNode(), true)) { + SDValue NewMask = getUnpackhMask(NumElems, DAG, dl); + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, V2, NewMask); } } } + // Normalize the node to match x86 shuffle ops if needed + if (V2.getOpcode() != ISD::UNDEF && isCommutedSHUFP(PermMask.getNode())) + Op = CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); + if (Commuted) { // Commute is back and try unpck* again. - // FIXME: this seems wrong. - SDValue NewOp = CommuteVectorShuffle(SVOp, DAG); - ShuffleVectorSDNode *NewSVOp = cast(NewOp); - if (X86::isUNPCKL_v_undef_Mask(NewSVOp) || - X86::isUNPCKH_v_undef_Mask(NewSVOp) || - X86::isUNPCKLMask(NewSVOp) || - X86::isUNPCKHMask(NewSVOp)) - return NewOp; + Op = CommuteVectorShuffle(Op, V1, V2, PermMask, DAG); + if (X86::isUNPCKL_v_undef_Mask(PermMask.getNode()) || + X86::isUNPCKH_v_undef_Mask(PermMask.getNode()) || + X86::isUNPCKLMask(PermMask.getNode()) || + X86::isUNPCKHMask(PermMask.getNode())) + return Op; } // FIXME: for mmx, bitcast v2i32 to v4i16 for shuffle. + // Try PSHUF* first, then SHUFP*. + // MMX doesn't have PSHUFD but it does have PSHUFW. While it's theoretically + // possible to shuffle a v2i32 using PSHUFW, that's not yet implemented. + if (isMMX && NumElems == 4 && X86::isPSHUFDMask(PermMask.getNode())) { + if (V2.getOpcode() != ISD::UNDEF) + return DAG.getNode(ISD::VECTOR_SHUFFLE, dl, VT, V1, + DAG.getUNDEF(VT), PermMask); + return Op; + } - // Normalize the node to match x86 shuffle ops if needed - if (!isMMX && V2.getOpcode() != ISD::UNDEF && isCommutedSHUFP(SVOp)) - return CommuteVectorShuffle(SVOp, DAG); + if (!isMMX) { + if (Subtarget->hasSSE2() && + (X86::isPSHUFDMask(PermMask.getNode()) || + X86::isPSHUFHWMask(PermMask.getNode()) || + X86::isPSHUFLWMask(PermMask.getNode()))) { + MVT RVT = VT; + if (VT == MVT::v4f32) { + RVT = MVT::v4i32; + Op = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, RVT, + DAG.getNode(ISD::BIT_CONVERT, dl, RVT, V1), + DAG.getUNDEF(RVT), PermMask); + } else if (V2.getOpcode() != ISD::UNDEF) + Op = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, RVT, V1, + DAG.getUNDEF(RVT), PermMask); + if (RVT != VT) + Op = DAG.getNode(ISD::BIT_CONVERT, dl, VT, Op); + return Op; + } + + // Binary or unary shufps. + if (X86::isSHUFPMask(PermMask.getNode()) || + (V2.getOpcode() == ISD::UNDEF && X86::isPSHUFDMask(PermMask.getNode()))) + return Op; + } - // Check for legal shuffle and return? - if (isShuffleMaskLegal(PermMask, VT)) - return Op; - // Handle v8i16 specifically since SSE can do byte extraction and insertion. if (VT == MVT::v8i16) { - SDValue NewOp = LowerVECTOR_SHUFFLEv8i16(SVOp, DAG, *this); + SDValue NewOp = LowerVECTOR_SHUFFLEv8i16(V1, V2, PermMask, DAG, *this, dl); if (NewOp.getNode()) return NewOp; } if (VT == MVT::v16i8) { - SDValue NewOp = LowerVECTOR_SHUFFLEv16i8(SVOp, DAG, *this); + SDValue NewOp = LowerVECTOR_SHUFFLEv16i8(V1, V2, PermMask, DAG, *this, dl); if (NewOp.getNode()) return NewOp; } // Handle all 4 wide cases with a number of shuffles except for MMX. if (NumElems == 4 && !isMMX) - return LowerVECTOR_SHUFFLE_4wide(SVOp, DAG); + return LowerVECTOR_SHUFFLE_4wide(V1, V2, PermMask, VT, DAG, dl); return SDValue(); } @@ -4229,12 +4529,22 @@ unsigned Idx = cast(Op.getOperand(1))->getZExtValue(); if (Idx == 0) return Op; - // SHUFPS the element to the lowest double word, then movss. - int Mask[4] = { Idx, -1, -1, -1 }; - MVT VVT = Op.getOperand(0).getValueType(); - SDValue Vec = DAG.getVectorShuffle(VVT, dl, Op.getOperand(0), - DAG.getUNDEF(VVT), Mask); + MVT MaskVT = MVT::getIntVectorWithNumElements(4); + SmallVector IdxVec; + IdxVec. + push_back(DAG.getConstant(Idx, MaskVT.getVectorElementType())); + IdxVec. + push_back(DAG.getUNDEF(MaskVT.getVectorElementType())); + IdxVec. + push_back(DAG.getUNDEF(MaskVT.getVectorElementType())); + IdxVec. + push_back(DAG.getUNDEF(MaskVT.getVectorElementType())); + SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &IdxVec[0], IdxVec.size()); + SDValue Vec = Op.getOperand(0); + Vec = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, Vec.getValueType(), + Vec, DAG.getUNDEF(Vec.getValueType()), Mask); return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, Vec, DAG.getIntPtrConstant(0)); } else if (VT.getSizeInBits() == 64) { @@ -4248,10 +4558,17 @@ // UNPCKHPD the element to the lowest double word, then movsd. // Note if the lower 64 bits of the result of the UNPCKHPD is then stored // to a f64mem, the whole operation is folded into a single MOVHPDmr. - int Mask[2] = { 1, -1 }; - MVT VVT = Op.getOperand(0).getValueType(); - SDValue Vec = DAG.getVectorShuffle(VVT, dl, Op.getOperand(0), - DAG.getUNDEF(VVT), Mask); + MVT MaskVT = MVT::getIntVectorWithNumElements(2); + SmallVector IdxVec; + IdxVec.push_back(DAG.getConstant(1, MaskVT.getVectorElementType())); + IdxVec. + push_back(DAG.getUNDEF(MaskVT.getVectorElementType())); + SDValue Mask = DAG.getNode(ISD::BUILD_VECTOR, dl, MaskVT, + &IdxVec[0], IdxVec.size()); + SDValue Vec = Op.getOperand(0); + Vec = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, Vec.getValueType(), + Vec, DAG.getUNDEF(Vec.getValueType()), + Mask); return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, Vec, DAG.getIntPtrConstant(0)); } @@ -4758,6 +5075,19 @@ Constant *C1 = ConstantVector::get(CV1); SDValue CPIdx1 = DAG.getConstantPool(C1, getPointerTy(), 16); + SmallVector MaskVec; + MaskVec.push_back(DAG.getConstant(0, MVT::i32)); + MaskVec.push_back(DAG.getConstant(4, MVT::i32)); + MaskVec.push_back(DAG.getConstant(1, MVT::i32)); + MaskVec.push_back(DAG.getConstant(5, MVT::i32)); + SDValue UnpcklMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, + &MaskVec[0], MaskVec.size()); + SmallVector MaskVec2; + MaskVec2.push_back(DAG.getConstant(1, MVT::i32)); + MaskVec2.push_back(DAG.getConstant(0, MVT::i32)); + SDValue ShufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i32, + &MaskVec2[0], MaskVec2.size()); + SDValue XR1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v4i32, DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op.getOperand(0), @@ -4766,11 +5096,13 @@ DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op.getOperand(0), DAG.getIntPtrConstant(0))); - SDValue Unpck1 = getUnpackl(DAG, dl, MVT::v4i32, XR1, XR2); + SDValue Unpck1 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v4i32, + XR1, XR2, UnpcklMask); SDValue CLod0 = DAG.getLoad(MVT::v4i32, dl, DAG.getEntryNode(), CPIdx0, PseudoSourceValue::getConstantPool(), 0, false, 16); - SDValue Unpck2 = getUnpackl(DAG, dl, MVT::v4i32, Unpck1, CLod0); + SDValue Unpck2 = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v4i32, + Unpck1, CLod0, UnpcklMask); SDValue XR2F = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2f64, Unpck2); SDValue CLod1 = DAG.getLoad(MVT::v2f64, dl, CLod0.getValue(1), CPIdx1, PseudoSourceValue::getConstantPool(), 0, @@ -4778,9 +5110,8 @@ SDValue Sub = DAG.getNode(ISD::FSUB, dl, MVT::v2f64, XR2F, CLod1); // Add the halves; easiest way is to swap them into another reg first. - int ShufMask[2] = { 1, -1 }; - SDValue Shuf = DAG.getVectorShuffle(MVT::v2f64, dl, Sub, - DAG.getUNDEF(MVT::v2f64), ShufMask); + SDValue Shuf = DAG.getNode(ISD::VECTOR_SHUFFLE, dl, MVT::v2f64, + Sub, Sub, ShufMask); SDValue Add = DAG.getNode(ISD::FADD, dl, MVT::v2f64, Shuf, Sub); return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Add, DAG.getIntPtrConstant(0)); @@ -6932,36 +7263,34 @@ /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values /// are assumed to be legal. bool -X86TargetLowering::isShuffleMaskLegal(const int *Mask, MVT VT) const { +X86TargetLowering::isShuffleMaskLegal(SDValue Mask, MVT VT) const { // Only do shuffles on 128-bit vector types for now. - if (VT.getSizeInBits() == 64) - return false; - - // FIXME: pshufb, blends, palignr, shifts. - return (VT.getVectorNumElements() == 2 || - ShuffleVectorSDNode::isSplatMask(Mask, VT) || - isMOVLMask(Mask, VT) || - isSHUFPMask(Mask, VT) || - isPSHUFDMask(Mask, VT) || - isPSHUFHWMask(Mask, VT) || - isPSHUFLWMask(Mask, VT) || - isUNPCKLMask(Mask, VT) || - isUNPCKHMask(Mask, VT) || - isUNPCKL_v_undef_Mask(Mask, VT) || - isUNPCKH_v_undef_Mask(Mask, VT)); + // FIXME: pshufb, blends + if (VT.getSizeInBits() == 64) return false; + return (Mask.getNode()->getNumOperands() <= 4 || + isIdentityMask(Mask.getNode()) || + isIdentityMask(Mask.getNode(), true) || + isSplatMask(Mask.getNode()) || + X86::isPSHUFHWMask(Mask.getNode()) || + X86::isPSHUFLWMask(Mask.getNode()) || + X86::isUNPCKLMask(Mask.getNode()) || + X86::isUNPCKHMask(Mask.getNode()) || + X86::isUNPCKL_v_undef_Mask(Mask.getNode()) || + X86::isUNPCKH_v_undef_Mask(Mask.getNode())); } bool -X86TargetLowering::isVectorClearMaskLegal(const int *Mask, MVT VT) const { - unsigned NumElts = VT.getVectorNumElements(); - // FIXME: This collection of masks seems suspect. - if (NumElts == 2) - return true; - if (NumElts == 4 && VT.getSizeInBits() == 128) { - return (isMOVLMask(Mask, VT) || - isCommutedMOVLMask(Mask, VT, true) || - isSHUFPMask(Mask, VT) || - isCommutedSHUFPMask(Mask, VT)); +X86TargetLowering::isVectorClearMaskLegal(const std::vector &BVOps, + MVT EVT, SelectionDAG &DAG) const { + unsigned NumElts = BVOps.size(); + // Only do shuffles on 128-bit vector types for now. + if (EVT.getSizeInBits() * NumElts == 64) return false; + if (NumElts == 2) return true; + if (NumElts == 4) { + return (isMOVLMask(&BVOps[0], 4) || + isCommutedMOVL(&BVOps[0], 4, true) || + isSHUFPMask(&BVOps[0], 4) || + isCommutedSHUFP(&BVOps[0], 4)); } return false; } @@ -7696,14 +8025,15 @@ return false; } -static bool EltsFromConsecutiveLoads(SDNode *N, const int *PermMask, +static bool EltsFromConsecutiveLoads(SDNode *N, SDValue PermMask, unsigned NumElems, MVT EVT, SDNode *&Base, SelectionDAG &DAG, MachineFrameInfo *MFI, const TargetLowering &TLI) { Base = NULL; for (unsigned i = 0; i < NumElems; ++i) { - if (PermMask[i] < 0) { + SDValue Idx = PermMask.getOperand(i); + if (Idx.getOpcode() == ISD::UNDEF) { if (!Base) return false; continue; @@ -7736,12 +8066,12 @@ /// shuffle to be an appropriate build vector so it can take advantage of // performBuildVectorCombine. static SDValue PerformShuffleCombine(SDNode *N, SelectionDAG &DAG, - const TargetLowering &TLI) { + const TargetLowering &TLI) { DebugLoc dl = N->getDebugLoc(); MVT VT = N->getValueType(0); MVT EVT = VT.getVectorElementType(); - const int *PermMask = cast(N)->getMask(); - unsigned NumElems = VT.getVectorNumElements(); + SDValue PermMask = N->getOperand(2); + unsigned NumElems = PermMask.getNumOperands(); // For x86-32 machines, if we see an insert and then a shuffle in a v2i64 // where the upper half is 0, it is advantageous to rewrite it as a build @@ -7750,10 +8080,9 @@ SDValue In[2]; In[0] = N->getOperand(0); In[1] = N->getOperand(1); - unsigned Idx0 = PermMask[0]; - unsigned Idx1 = PermMask[1]; - // FIXME: can we take advantage of undef index? - if (PermMask[0] >= 0 && PermMask[1] >= 0 && + unsigned Idx0 =cast(PermMask.getOperand(0))->getZExtValue(); + unsigned Idx1 =cast(PermMask.getOperand(1))->getZExtValue(); + if (In[0].getValueType().getVectorNumElements() == NumElems && In[Idx0/2].getOpcode() == ISD::INSERT_VECTOR_ELT && In[Idx1/2].getOpcode() == ISD::BUILD_VECTOR) { ConstantSDNode* InsertVecIdx = @@ -8217,9 +8546,9 @@ } } } else if (ShAmtOp.getOpcode() == ISD::VECTOR_SHUFFLE && - cast(ShAmtOp)->isSplat()) { - BaseShAmt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, ShAmtOp, - DAG.getIntPtrConstant(0)); + isSplatMask(ShAmtOp.getOperand(2).getNode())) { + BaseShAmt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, ShAmtOp, + DAG.getIntPtrConstant(0)); } else 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=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Fri Apr 24 07:40:33 2009 @@ -230,8 +230,7 @@ // VSHL, VSRL - Vector logical left / right shift. VSHL, VSRL, - - // CMPPD, CMPPS - Vector double/float comparison. + // CMPPD, CMPPS - Vector double/float comparison. CMPPD, CMPPS, @@ -252,72 +251,80 @@ namespace X86 { /// isPSHUFDMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to PSHUFD. - bool isPSHUFDMask(ShuffleVectorSDNode *N); + bool isPSHUFDMask(SDNode *N); /// isPSHUFHWMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to PSHUFD. - bool isPSHUFHWMask(ShuffleVectorSDNode *N); + bool isPSHUFHWMask(SDNode *N); /// isPSHUFLWMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to PSHUFD. - bool isPSHUFLWMask(ShuffleVectorSDNode *N); + bool isPSHUFLWMask(SDNode *N); /// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to SHUFP*. - bool isSHUFPMask(ShuffleVectorSDNode *N); + bool isSHUFPMask(SDNode *N); /// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVHLPS. - bool isMOVHLPSMask(ShuffleVectorSDNode *N); + bool isMOVHLPSMask(SDNode *N); /// isMOVHLPS_v_undef_Mask - Special case of isMOVHLPSMask for canonical form /// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef, /// <2, 3, 2, 3> - bool isMOVHLPS_v_undef_Mask(ShuffleVectorSDNode *N); + bool isMOVHLPS_v_undef_Mask(SDNode *N); /// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand - /// specifies a shuffle of elements that is suitable for MOVLP{S|D}. - bool isMOVLPMask(ShuffleVectorSDNode *N); + /// specifies a shuffle of elements that is suitable for input to MOVLP{S|D}. + bool isMOVLPMask(SDNode *N); /// isMOVHPMask - Return true if the specified VECTOR_SHUFFLE operand - /// specifies a shuffle of elements that is suitable for MOVHP{S|D}. + /// specifies a shuffle of elements that is suitable for input to MOVHP{S|D} /// as well as MOVLHPS. - bool isMOVHPMask(ShuffleVectorSDNode *N); + bool isMOVHPMask(SDNode *N); /// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKL. - bool isUNPCKLMask(ShuffleVectorSDNode *N, bool V2IsSplat = false); + bool isUNPCKLMask(SDNode *N, bool V2IsSplat = false); /// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKH. - bool isUNPCKHMask(ShuffleVectorSDNode *N, bool V2IsSplat = false); + bool isUNPCKHMask(SDNode *N, bool V2IsSplat = false); /// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form /// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef, /// <0, 0, 1, 1> - bool isUNPCKL_v_undef_Mask(ShuffleVectorSDNode *N); + bool isUNPCKL_v_undef_Mask(SDNode *N); /// isUNPCKH_v_undef_Mask - Special case of isUNPCKHMask for canonical form /// of vector_shuffle v, v, <2, 6, 3, 7>, i.e. vector_shuffle v, undef, /// <2, 2, 3, 3> - bool isUNPCKH_v_undef_Mask(ShuffleVectorSDNode *N); + bool isUNPCKH_v_undef_Mask(SDNode *N); /// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSS, /// MOVSD, and MOVD, i.e. setting the lowest element. - bool isMOVLMask(ShuffleVectorSDNode *N); + bool isMOVLMask(SDNode *N); /// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSHDUP. - bool isMOVSHDUPMask(ShuffleVectorSDNode *N); + bool isMOVSHDUPMask(SDNode *N); /// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSLDUP. - bool isMOVSLDUPMask(ShuffleVectorSDNode *N); + bool isMOVSLDUPMask(SDNode *N); + + /// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a splat of a single element. + bool isSplatMask(SDNode *N); + + /// isSplatLoMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a splat of zero element. + bool isSplatLoMask(SDNode *N); /// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVDDUP. - bool isMOVDDUPMask(ShuffleVectorSDNode *N); + bool isMOVDDUPMask(SDNode *N); /// getShuffleSHUFImmediate - Return the appropriate immediate to shuffle /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUF* and SHUFP* @@ -470,13 +477,14 @@ /// support *some* VECTOR_SHUFFLE operations, those with specific masks. /// By default, if a target supports the VECTOR_SHUFFLE node, all mask /// values are assumed to be legal. - virtual bool isShuffleMaskLegal(const int *Mask, MVT VT) const; + virtual bool isShuffleMaskLegal(SDValue Mask, MVT VT) const; /// isVectorClearMaskLegal - Similar to isShuffleMaskLegal. This is /// used by Targets can use this to indicate if there is a suitable /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant /// pool entry. - virtual bool isVectorClearMaskLegal(const int *Mask, MVT VT) const; + virtual bool isVectorClearMaskLegal(const std::vector &BVOps, + MVT EVT, SelectionDAG &DAG) const; /// ShouldShrinkFPConstant - If true, then instruction selection should /// seek to shrink the FP constant of the specified type to a smaller type Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Fri Apr 24 07:40:33 2009 @@ -3801,7 +3801,6 @@ (implicit EFLAGS)), (DEC32m addr:$dst)>, Requires<[In32BitMode]>; - //===----------------------------------------------------------------------===// // Floating Point Stack Support //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/Target/X86/X86InstrMMX.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrMMX.td?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrMMX.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrMMX.td Fri Apr 24 07:40:33 2009 @@ -30,37 +30,33 @@ // MMX_SHUFFLE_get_shuf_imm xform function: convert vector_shuffle mask to // PSHUFW imm. -def MMX_SHUFFLE_get_shuf_imm : SDNodeXForm; // Patterns for: vector_shuffle v1, v2, <2, 6, 3, 7, ...> -def mmx_unpckh : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isUNPCKHMask(cast(N)); +def MMX_UNPCKH_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isUNPCKHMask(N); }]>; // Patterns for: vector_shuffle v1, v2, <0, 4, 2, 5, ...> -def mmx_unpckl : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isUNPCKLMask(cast(N)); +def MMX_UNPCKL_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isUNPCKLMask(N); }]>; // Patterns for: vector_shuffle v1, , <0, 0, 1, 1, ...> -def mmx_unpckh_undef : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isUNPCKH_v_undef_Mask(cast(N)); +def MMX_UNPCKH_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isUNPCKH_v_undef_Mask(N); }]>; // Patterns for: vector_shuffle v1, , <2, 2, 3, 3, ...> -def mmx_unpckl_undef : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isUNPCKL_v_undef_Mask(cast(N)); +def MMX_UNPCKL_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isUNPCKL_v_undef_Mask(N); }]>; -def mmx_pshufw : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isPSHUFDMask(cast(N)); +// Patterns for shuffling. +def MMX_PSHUFW_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isPSHUFDMask(N); }], MMX_SHUFFLE_get_shuf_imm>; //===----------------------------------------------------------------------===// @@ -189,8 +185,9 @@ def MMX_MOVQ2DQrr : SSDIi8<0xD6, MRMDestMem, (outs VR128:$dst), (ins VR64:$src), "movq2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, - (movl immAllZerosV, - (v2i64 (scalar_to_vector (i64 (bitconvert VR64:$src))))))]>; + (v2i64 (vector_shuffle immAllZerosV, + (v2i64 (scalar_to_vector (i64 (bitconvert VR64:$src)))), + MOVL_shuffle_mask)))]>; let neverHasSideEffects = 1 in def MMX_MOVQ2FR64rr: SSDIi8<0xD6, MRMDestMem, (outs FR64:$dst), (ins VR64:$src), @@ -322,74 +319,86 @@ (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpckhbw\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v8i8 (mmx_unpckh VR64:$src1, VR64:$src2)))]>; + (v8i8 (vector_shuffle VR64:$src1, VR64:$src2, + MMX_UNPCKH_shuffle_mask)))]>; def MMX_PUNPCKHBWrm : MMXI<0x68, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpckhbw\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v8i8 (mmx_unpckh VR64:$src1, - (bc_v8i8 (load_mmx addr:$src2)))))]>; + (v8i8 (vector_shuffle VR64:$src1, + (bc_v8i8 (load_mmx addr:$src2)), + MMX_UNPCKH_shuffle_mask)))]>; def MMX_PUNPCKHWDrr : MMXI<0x69, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpckhwd\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v4i16 (mmx_unpckh VR64:$src1, VR64:$src2)))]>; + (v4i16 (vector_shuffle VR64:$src1, VR64:$src2, + MMX_UNPCKH_shuffle_mask)))]>; def MMX_PUNPCKHWDrm : MMXI<0x69, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpckhwd\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v4i16 (mmx_unpckh VR64:$src1, - (bc_v4i16 (load_mmx addr:$src2)))))]>; + (v4i16 (vector_shuffle VR64:$src1, + (bc_v4i16 (load_mmx addr:$src2)), + MMX_UNPCKH_shuffle_mask)))]>; def MMX_PUNPCKHDQrr : MMXI<0x6A, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpckhdq\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v2i32 (mmx_unpckh VR64:$src1, VR64:$src2)))]>; + (v2i32 (vector_shuffle VR64:$src1, VR64:$src2, + MMX_UNPCKH_shuffle_mask)))]>; def MMX_PUNPCKHDQrm : MMXI<0x6A, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpckhdq\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v2i32 (mmx_unpckh VR64:$src1, - (bc_v2i32 (load_mmx addr:$src2)))))]>; + (v2i32 (vector_shuffle VR64:$src1, + (bc_v2i32 (load_mmx addr:$src2)), + MMX_UNPCKH_shuffle_mask)))]>; // Unpack Low Packed Data Instructions def MMX_PUNPCKLBWrr : MMXI<0x60, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpcklbw\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v8i8 (mmx_unpckl VR64:$src1, VR64:$src2)))]>; + (v8i8 (vector_shuffle VR64:$src1, VR64:$src2, + MMX_UNPCKL_shuffle_mask)))]>; def MMX_PUNPCKLBWrm : MMXI<0x60, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpcklbw\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v8i8 (mmx_unpckl VR64:$src1, - (bc_v8i8 (load_mmx addr:$src2)))))]>; + (v8i8 (vector_shuffle VR64:$src1, + (bc_v8i8 (load_mmx addr:$src2)), + MMX_UNPCKL_shuffle_mask)))]>; def MMX_PUNPCKLWDrr : MMXI<0x61, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpcklwd\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v4i16 (mmx_unpckl VR64:$src1, VR64:$src2)))]>; + (v4i16 (vector_shuffle VR64:$src1, VR64:$src2, + MMX_UNPCKL_shuffle_mask)))]>; def MMX_PUNPCKLWDrm : MMXI<0x61, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpcklwd\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v4i16 (mmx_unpckl VR64:$src1, - (bc_v4i16 (load_mmx addr:$src2)))))]>; + (v4i16 (vector_shuffle VR64:$src1, + (bc_v4i16 (load_mmx addr:$src2)), + MMX_UNPCKL_shuffle_mask)))]>; def MMX_PUNPCKLDQrr : MMXI<0x62, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), "punpckldq\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v2i32 (mmx_unpckl VR64:$src1, VR64:$src2)))]>; + (v2i32 (vector_shuffle VR64:$src1, VR64:$src2, + MMX_UNPCKL_shuffle_mask)))]>; def MMX_PUNPCKLDQrm : MMXI<0x62, MRMSrcMem, (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), "punpckldq\t{$src2, $dst|$dst, $src2}", [(set VR64:$dst, - (v2i32 (mmx_unpckl VR64:$src1, - (bc_v2i32 (load_mmx addr:$src2)))))]>; + (v2i32 (vector_shuffle VR64:$src1, + (bc_v2i32 (load_mmx addr:$src2)), + MMX_UNPCKL_shuffle_mask)))]>; } // -- Pack Instructions @@ -402,13 +411,17 @@ (outs VR64:$dst), (ins VR64:$src1, i8imm:$src2), "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", [(set VR64:$dst, - (v4i16 (mmx_pshufw:$src2 VR64:$src1, (undef))))]>; + (v4i16 (vector_shuffle + VR64:$src1, (undef), + MMX_PSHUFW_shuffle_mask:$src2)))]>; def MMX_PSHUFWmi : MMXIi8<0x70, MRMSrcMem, (outs VR64:$dst), (ins i64mem:$src1, i8imm:$src2), "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", [(set VR64:$dst, - (mmx_pshufw:$src2 (bc_v4i16 (load_mmx addr:$src1)), - (undef)))]>; + (v4i16 (vector_shuffle + (bc_v4i16 (load_mmx addr:$src1)), + (undef), + MMX_PSHUFW_shuffle_mask:$src2)))]>; // -- Conversion Instructions let neverHasSideEffects = 1 in { @@ -614,27 +627,34 @@ // Patterns to perform canonical versions of vector shuffling. let AddedComplexity = 10 in { - def : Pat<(v8i8 (mmx_unpckl_undef VR64:$src, (undef))), + def : Pat<(v8i8 (vector_shuffle VR64:$src, (undef), + MMX_UNPCKL_v_undef_shuffle_mask)), (MMX_PUNPCKLBWrr VR64:$src, VR64:$src)>; - def : Pat<(v4i16 (mmx_unpckl_undef VR64:$src, (undef))), + def : Pat<(v4i16 (vector_shuffle VR64:$src, (undef), + MMX_UNPCKL_v_undef_shuffle_mask)), (MMX_PUNPCKLWDrr VR64:$src, VR64:$src)>; - def : Pat<(v2i32 (mmx_unpckl_undef VR64:$src, (undef))), + def : Pat<(v2i32 (vector_shuffle VR64:$src, (undef), + MMX_UNPCKL_v_undef_shuffle_mask)), (MMX_PUNPCKLDQrr VR64:$src, VR64:$src)>; } let AddedComplexity = 10 in { - def : Pat<(v8i8 (mmx_unpckh_undef VR64:$src, (undef))), + def : Pat<(v8i8 (vector_shuffle VR64:$src, (undef), + MMX_UNPCKH_v_undef_shuffle_mask)), (MMX_PUNPCKHBWrr VR64:$src, VR64:$src)>; - def : Pat<(v4i16 (mmx_unpckh_undef VR64:$src, (undef))), + def : Pat<(v4i16 (vector_shuffle VR64:$src, (undef), + MMX_UNPCKH_v_undef_shuffle_mask)), (MMX_PUNPCKHWDrr VR64:$src, VR64:$src)>; - def : Pat<(v2i32 (mmx_unpckh_undef VR64:$src, (undef))), + def : Pat<(v2i32 (vector_shuffle VR64:$src, (undef), + MMX_UNPCKH_v_undef_shuffle_mask)), (MMX_PUNPCKHDQrr VR64:$src, VR64:$src)>; } // Patterns to perform vector shuffling with a zeroed out vector. let AddedComplexity = 20 in { - def : Pat<(bc_v2i32 (mmx_unpckl immAllZerosV, - (v2i32 (scalar_to_vector (load_mmx addr:$src))))), + def : Pat<(bc_v2i32 (vector_shuffle immAllZerosV, + (v2i32 (scalar_to_vector (load_mmx addr:$src))), + MMX_UNPCKL_shuffle_mask)), (MMX_PUNPCKLDQrm VR64:$src, VR64:$src)>; } Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Fri Apr 24 07:40:33 2009 @@ -175,108 +175,103 @@ // SHUFFLE_get_shuf_imm xform function: convert vector_shuffle mask to PSHUF*, // SHUFP* etc. imm. -def SHUFFLE_get_shuf_imm : SDNodeXForm; // SHUFFLE_get_pshufhw_imm xform function: convert vector_shuffle mask to // PSHUFHW imm. -def SHUFFLE_get_pshufhw_imm : SDNodeXForm; // SHUFFLE_get_pshuflw_imm xform function: convert vector_shuffle mask to // PSHUFLW imm. -def SHUFFLE_get_pshuflw_imm : SDNodeXForm; -def splat_lo : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - ShuffleVectorSDNode *SVOp = cast(N); - return SVOp->isSplat() && SVOp->getSplatIndex() == 0; -}]>; +def SSE_splat_mask : PatLeaf<(build_vector), [{ + return X86::isSplatMask(N); +}], SHUFFLE_get_shuf_imm>; -def movddup : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isMOVDDUPMask(cast(N)); +def SSE_splat_lo_mask : PatLeaf<(build_vector), [{ + return X86::isSplatLoMask(N); }]>; -def movhlps : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isMOVHLPSMask(cast(N)); +def MOVDDUP_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isMOVDDUPMask(N); }]>; -def movhlps_undef : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isMOVHLPS_v_undef_Mask(cast(N)); +def MOVHLPS_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isMOVHLPSMask(N); }]>; -def movhp : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isMOVHPMask(cast(N)); +def MOVHLPS_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isMOVHLPS_v_undef_Mask(N); }]>; -def movlp : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isMOVLPMask(cast(N)); +def MOVHP_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isMOVHPMask(N); }]>; -def movl : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isMOVLMask(cast(N)); +def MOVLP_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isMOVLPMask(N); }]>; -def movshdup : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isMOVSHDUPMask(cast(N)); +def MOVL_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isMOVLMask(N); }]>; -def movsldup : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isMOVSLDUPMask(cast(N)); +def MOVSHDUP_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isMOVSHDUPMask(N); }]>; -def unpckl : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isUNPCKLMask(cast(N)); +def MOVSLDUP_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isMOVSLDUPMask(N); }]>; -def unpckh : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isUNPCKHMask(cast(N)); +def UNPCKL_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isUNPCKLMask(N); }]>; -def unpckl_undef : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isUNPCKL_v_undef_Mask(cast(N)); +def UNPCKH_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isUNPCKHMask(N); }]>; -def unpckh_undef : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isUNPCKH_v_undef_Mask(cast(N)); +def UNPCKL_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isUNPCKL_v_undef_Mask(N); }]>; -def pshufd : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isPSHUFDMask(cast(N)); -}], SHUFFLE_get_shuf_imm>; +def UNPCKH_v_undef_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isUNPCKH_v_undef_Mask(N); +}]>; -def shufp : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isSHUFPMask(cast(N)); +def PSHUFD_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isPSHUFDMask(N); }], SHUFFLE_get_shuf_imm>; -def pshufhw : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isPSHUFHWMask(cast(N)); +def PSHUFHW_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isPSHUFHWMask(N); }], SHUFFLE_get_pshufhw_imm>; -def pshuflw : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ - return X86::isPSHUFLWMask(cast(N)); +def PSHUFLW_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isPSHUFLWMask(N); }], SHUFFLE_get_pshuflw_imm>; +def SHUFP_unary_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isPSHUFDMask(N); +}], SHUFFLE_get_shuf_imm>; + +def SHUFP_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isSHUFPMask(N); +}], SHUFFLE_get_shuf_imm>; + +def PSHUFD_binary_shuffle_mask : PatLeaf<(build_vector), [{ + return X86::isSHUFPMask(N); +}], SHUFFLE_get_shuf_imm>; + + //===----------------------------------------------------------------------===// // SSE scalar FP Instructions //===----------------------------------------------------------------------===// @@ -709,14 +704,16 @@ (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), "movlps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (movlp VR128:$src1, - (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))))]>; + (v4f32 (vector_shuffle VR128:$src1, + (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2)))), + MOVLP_shuffle_mask)))]>; def MOVHPSrm : PSI<0x16, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), "movhps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (movhp VR128:$src1, - (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))))]>; + (v4f32 (vector_shuffle VR128:$src1, + (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2)))), + MOVHP_shuffle_mask)))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" @@ -731,25 +728,29 @@ def MOVHPSmr : PSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movhps\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract - (unpckh (bc_v2f64 (v4f32 VR128:$src)), - (undef)), (iPTR 0))), addr:$dst)]>; + (v2f64 (vector_shuffle + (bc_v2f64 (v4f32 VR128:$src)), (undef), + UNPCKH_shuffle_mask)), (iPTR 0))), + addr:$dst)]>; let Constraints = "$src1 = $dst" in { let AddedComplexity = 20 in { def MOVLHPSrr : PSI<0x16, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "movlhps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (movhp VR128:$src1, VR128:$src2)))]>; + (v4f32 (vector_shuffle VR128:$src1, VR128:$src2, + MOVHP_shuffle_mask)))]>; def MOVHLPSrr : PSI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "movhlps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (movhlps VR128:$src1, VR128:$src2)))]>; + (v4f32 (vector_shuffle VR128:$src1, VR128:$src2, + MOVHLPS_shuffle_mask)))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" let AddedComplexity = 20 in -def : Pat<(v4f32 (movddup VR128:$src, (undef))), +def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), MOVDDUP_shuffle_mask)), (MOVLHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; @@ -907,41 +908,51 @@ let isConvertibleToThreeAddress = 1 in // Convert to pshufd def SHUFPSrri : PSIi8<0xC6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, - VR128:$src2, i8imm:$src3), + VR128:$src2, i32i8imm:$src3), "shufps\t{$src3, $src2, $dst|$dst, $src2, $src3}", [(set VR128:$dst, - (v4f32 (shufp:$src3 VR128:$src1, VR128:$src2)))]>; + (v4f32 (vector_shuffle + VR128:$src1, VR128:$src2, + SHUFP_shuffle_mask:$src3)))]>; def SHUFPSrmi : PSIi8<0xC6, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, - f128mem:$src2, i8imm:$src3), + f128mem:$src2, i32i8imm:$src3), "shufps\t{$src3, $src2, $dst|$dst, $src2, $src3}", [(set VR128:$dst, - (v4f32 (shufp:$src3 - VR128:$src1, (memopv4f32 addr:$src2))))]>; + (v4f32 (vector_shuffle + VR128:$src1, (memopv4f32 addr:$src2), + SHUFP_shuffle_mask:$src3)))]>; let AddedComplexity = 10 in { def UNPCKHPSrr : PSI<0x15, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "unpckhps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (unpckh VR128:$src1, VR128:$src2)))]>; + (v4f32 (vector_shuffle + VR128:$src1, VR128:$src2, + UNPCKH_shuffle_mask)))]>; def UNPCKHPSrm : PSI<0x15, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), "unpckhps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (unpckh VR128:$src1, - (memopv4f32 addr:$src2))))]>; + (v4f32 (vector_shuffle + VR128:$src1, (memopv4f32 addr:$src2), + UNPCKH_shuffle_mask)))]>; def UNPCKLPSrr : PSI<0x14, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "unpcklps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (unpckl VR128:$src1, VR128:$src2)))]>; + (v4f32 (vector_shuffle + VR128:$src1, VR128:$src2, + UNPCKL_shuffle_mask)))]>; def UNPCKLPSrm : PSI<0x14, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), "unpcklps\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (unpckl VR128:$src1, (memopv4f32 addr:$src2)))]>; + (v4f32 (vector_shuffle + VR128:$src1, (memopv4f32 addr:$src2), + UNPCKL_shuffle_mask)))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" @@ -1033,7 +1044,8 @@ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "movss\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4f32 (movl VR128:$src1, VR128:$src2)))]>; + (v4f32 (vector_shuffle VR128:$src1, VR128:$src2, + MOVL_shuffle_mask)))]>; } // Move to lower bits of a VR128 and zeroing upper bits. @@ -1439,14 +1451,16 @@ (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), "movlpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (movlp VR128:$src1, - (scalar_to_vector (loadf64 addr:$src2)))))]>; + (v2f64 (vector_shuffle VR128:$src1, + (scalar_to_vector (loadf64 addr:$src2)), + MOVLP_shuffle_mask)))]>; def MOVHPDrm : PDI<0x16, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), "movhpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (movhp VR128:$src1, - (scalar_to_vector (loadf64 addr:$src2)))))]>; + (v2f64 (vector_shuffle VR128:$src1, + (scalar_to_vector (loadf64 addr:$src2)), + MOVHP_shuffle_mask)))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" @@ -1460,8 +1474,9 @@ def MOVHPDmr : PDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movhpd\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract - (v2f64 (unpckh VR128:$src, (undef))), - (iPTR 0))), addr:$dst)]>; + (v2f64 (vector_shuffle VR128:$src, (undef), + UNPCKH_shuffle_mask)), (iPTR 0))), + addr:$dst)]>; // SSE2 instructions without OpSize prefix def Int_CVTDQ2PSrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), @@ -1729,39 +1744,48 @@ def SHUFPDrri : PDIi8<0xC6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2, i8imm:$src3), "shufpd\t{$src3, $src2, $dst|$dst, $src2, $src3}", - [(set VR128:$dst, - (v2f64 (shufp:$src3 VR128:$src1, VR128:$src2)))]>; + [(set VR128:$dst, (v2f64 (vector_shuffle + VR128:$src1, VR128:$src2, + SHUFP_shuffle_mask:$src3)))]>; def SHUFPDrmi : PDIi8<0xC6, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2, i8imm:$src3), "shufpd\t{$src3, $src2, $dst|$dst, $src2, $src3}", [(set VR128:$dst, - (v2f64 (shufp:$src3 - VR128:$src1, (memopv2f64 addr:$src2))))]>; + (v2f64 (vector_shuffle + VR128:$src1, (memopv2f64 addr:$src2), + SHUFP_shuffle_mask:$src3)))]>; let AddedComplexity = 10 in { def UNPCKHPDrr : PDI<0x15, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "unpckhpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (unpckh VR128:$src1, VR128:$src2)))]>; + (v2f64 (vector_shuffle + VR128:$src1, VR128:$src2, + UNPCKH_shuffle_mask)))]>; def UNPCKHPDrm : PDI<0x15, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), "unpckhpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (unpckh VR128:$src1, - (memopv2f64 addr:$src2))))]>; + (v2f64 (vector_shuffle + VR128:$src1, (memopv2f64 addr:$src2), + UNPCKH_shuffle_mask)))]>; def UNPCKLPDrr : PDI<0x14, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "unpcklpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (unpckl VR128:$src1, VR128:$src2)))]>; + (v2f64 (vector_shuffle + VR128:$src1, VR128:$src2, + UNPCKL_shuffle_mask)))]>; def UNPCKLPDrm : PDI<0x14, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), "unpcklpd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (unpckl VR128:$src1, (memopv2f64 addr:$src2)))]>; + (v2f64 (vector_shuffle + VR128:$src1, (memopv2f64 addr:$src2), + UNPCKL_shuffle_mask)))]>; } // AddedComplexity } // Constraints = "$src1 = $dst" @@ -2019,43 +2043,49 @@ def PSHUFDri : PDIi8<0x70, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), "pshufd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v4i32 (pshufd:$src2 - VR128:$src1, (undef))))]>; + [(set VR128:$dst, (v4i32 (vector_shuffle + VR128:$src1, (undef), + PSHUFD_shuffle_mask:$src2)))]>; def PSHUFDmi : PDIi8<0x70, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src1, i8imm:$src2), "pshufd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v4i32 (pshufd:$src2 + [(set VR128:$dst, (v4i32 (vector_shuffle (bc_v4i32(memopv2i64 addr:$src1)), - (undef))))]>; + (undef), + PSHUFD_shuffle_mask:$src2)))]>; // SSE2 with ImmT == Imm8 and XS prefix. def PSHUFHWri : Ii8<0x70, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), "pshufhw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v8i16 (pshufhw:$src2 VR128:$src1, - (undef))))]>, + [(set VR128:$dst, (v8i16 (vector_shuffle + VR128:$src1, (undef), + PSHUFHW_shuffle_mask:$src2)))]>, XS, Requires<[HasSSE2]>; def PSHUFHWmi : Ii8<0x70, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src1, i8imm:$src2), "pshufhw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v8i16 (pshufhw:$src2 - (bc_v8i16 (memopv2i64 addr:$src1)), - (undef))))]>, + [(set VR128:$dst, (v8i16 (vector_shuffle + (bc_v8i16 (memopv2i64 addr:$src1)), + (undef), + PSHUFHW_shuffle_mask:$src2)))]>, XS, Requires<[HasSSE2]>; // SSE2 with ImmT == Imm8 and XD prefix. def PSHUFLWri : Ii8<0x70, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), + (outs VR128:$dst), (ins VR128:$src1, i32i8imm:$src2), "pshuflw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v8i16 (pshuflw:$src2 VR128:$src1, - (undef))))]>, + [(set VR128:$dst, (v8i16 (vector_shuffle + VR128:$src1, (undef), + PSHUFLW_shuffle_mask:$src2)))]>, XD, Requires<[HasSSE2]>; def PSHUFLWmi : Ii8<0x70, MRMSrcMem, - (outs VR128:$dst), (ins i128mem:$src1, i8imm:$src2), + (outs VR128:$dst), (ins i128mem:$src1, i32i8imm:$src2), "pshuflw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (v8i16 (pshuflw:$src2 - (bc_v8i16 (memopv2i64 addr:$src1)), - (undef))))]>, + [(set VR128:$dst, (v8i16 (vector_shuffle + (bc_v8i16 (memopv2i64 addr:$src1)), + (undef), + PSHUFLW_shuffle_mask:$src2)))]>, XD, Requires<[HasSSE2]>; @@ -2064,91 +2094,107 @@ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpcklbw\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v16i8 (unpckl VR128:$src1, VR128:$src2)))]>; + (v16i8 (vector_shuffle VR128:$src1, VR128:$src2, + UNPCKL_shuffle_mask)))]>; def PUNPCKLBWrm : PDI<0x60, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpcklbw\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (unpckl VR128:$src1, - (bc_v16i8 (memopv2i64 addr:$src2))))]>; + (v16i8 (vector_shuffle VR128:$src1, + (bc_v16i8 (memopv2i64 addr:$src2)), + UNPCKL_shuffle_mask)))]>; def PUNPCKLWDrr : PDI<0x61, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpcklwd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v8i16 (unpckl VR128:$src1, VR128:$src2)))]>; + (v8i16 (vector_shuffle VR128:$src1, VR128:$src2, + UNPCKL_shuffle_mask)))]>; def PUNPCKLWDrm : PDI<0x61, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpcklwd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (unpckl VR128:$src1, - (bc_v8i16 (memopv2i64 addr:$src2))))]>; + (v8i16 (vector_shuffle VR128:$src1, + (bc_v8i16 (memopv2i64 addr:$src2)), + UNPCKL_shuffle_mask)))]>; def PUNPCKLDQrr : PDI<0x62, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckldq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4i32 (unpckl VR128:$src1, VR128:$src2)))]>; + (v4i32 (vector_shuffle VR128:$src1, VR128:$src2, + UNPCKL_shuffle_mask)))]>; def PUNPCKLDQrm : PDI<0x62, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckldq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (unpckl VR128:$src1, - (bc_v4i32 (memopv2i64 addr:$src2))))]>; + (v4i32 (vector_shuffle VR128:$src1, + (bc_v4i32 (memopv2i64 addr:$src2)), + UNPCKL_shuffle_mask)))]>; def PUNPCKLQDQrr : PDI<0x6C, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpcklqdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2i64 (unpckl VR128:$src1, VR128:$src2)))]>; + (v2i64 (vector_shuffle VR128:$src1, VR128:$src2, + UNPCKL_shuffle_mask)))]>; def PUNPCKLQDQrm : PDI<0x6C, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpcklqdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2i64 (unpckl VR128:$src1, - (memopv2i64 addr:$src2))))]>; + (v2i64 (vector_shuffle VR128:$src1, + (memopv2i64 addr:$src2), + UNPCKL_shuffle_mask)))]>; def PUNPCKHBWrr : PDI<0x68, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckhbw\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v16i8 (unpckh VR128:$src1, VR128:$src2)))]>; + (v16i8 (vector_shuffle VR128:$src1, VR128:$src2, + UNPCKH_shuffle_mask)))]>; def PUNPCKHBWrm : PDI<0x68, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckhbw\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (unpckh VR128:$src1, - (bc_v16i8 (memopv2i64 addr:$src2))))]>; + [(set VR128:$dst, + (v16i8 (vector_shuffle VR128:$src1, + (bc_v16i8 (memopv2i64 addr:$src2)), + UNPCKH_shuffle_mask)))]>; def PUNPCKHWDrr : PDI<0x69, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckhwd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v8i16 (unpckh VR128:$src1, VR128:$src2)))]>; + (v8i16 (vector_shuffle VR128:$src1, VR128:$src2, + UNPCKH_shuffle_mask)))]>; def PUNPCKHWDrm : PDI<0x69, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckhwd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (unpckh VR128:$src1, - (bc_v8i16 (memopv2i64 addr:$src2))))]>; + (v8i16 (vector_shuffle VR128:$src1, + (bc_v8i16 (memopv2i64 addr:$src2)), + UNPCKH_shuffle_mask)))]>; def PUNPCKHDQrr : PDI<0x6A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckhdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v4i32 (unpckh VR128:$src1, VR128:$src2)))]>; + (v4i32 (vector_shuffle VR128:$src1, VR128:$src2, + UNPCKH_shuffle_mask)))]>; def PUNPCKHDQrm : PDI<0x6A, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckhdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (unpckh VR128:$src1, - (bc_v4i32 (memopv2i64 addr:$src2))))]>; + (v4i32 (vector_shuffle VR128:$src1, + (bc_v4i32 (memopv2i64 addr:$src2)), + UNPCKH_shuffle_mask)))]>; def PUNPCKHQDQrr : PDI<0x6D, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "punpckhqdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2i64 (unpckh VR128:$src1, VR128:$src2)))]>; + (v2i64 (vector_shuffle VR128:$src1, VR128:$src2, + UNPCKH_shuffle_mask)))]>; def PUNPCKHQDQrm : PDI<0x6D, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), "punpckhqdq\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2i64 (unpckh VR128:$src1, - (memopv2i64 addr:$src2))))]>; + (v2i64 (vector_shuffle VR128:$src1, + (memopv2i64 addr:$src2), + UNPCKH_shuffle_mask)))]>; } // Extract / Insert @@ -2311,7 +2357,8 @@ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "movsd\t{$src2, $dst|$dst, $src2}", [(set VR128:$dst, - (v2f64 (movl VR128:$src1, VR128:$src2)))]>; + (v2f64 (vector_shuffle VR128:$src1, VR128:$src2, + MOVL_shuffle_mask)))]>; } // Store / copy lower 64-bits of a XMM register. @@ -2402,35 +2449,44 @@ // Move Instructions def MOVSHDUPrr : S3SI<0x16, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movshdup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4f32 (movshdup - VR128:$src, (undef))))]>; + [(set VR128:$dst, (v4f32 (vector_shuffle + VR128:$src, (undef), + MOVSHDUP_shuffle_mask)))]>; def MOVSHDUPrm : S3SI<0x16, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movshdup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (movshdup - (memopv4f32 addr:$src), (undef)))]>; + [(set VR128:$dst, (v4f32 (vector_shuffle + (memopv4f32 addr:$src), (undef), + MOVSHDUP_shuffle_mask)))]>; def MOVSLDUPrr : S3SI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movsldup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4f32 (movsldup - VR128:$src, (undef))))]>; + [(set VR128:$dst, (v4f32 (vector_shuffle + VR128:$src, (undef), + MOVSLDUP_shuffle_mask)))]>; def MOVSLDUPrm : S3SI<0x12, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movsldup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (movsldup - (memopv4f32 addr:$src), (undef)))]>; + [(set VR128:$dst, (v4f32 (vector_shuffle + (memopv4f32 addr:$src), (undef), + MOVSLDUP_shuffle_mask)))]>; def MOVDDUPrr : S3DI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movddup\t{$src, $dst|$dst, $src}", - [(set VR128:$dst,(v2f64 (movddup VR128:$src, (undef))))]>; + [(set VR128:$dst, + (v2f64 (vector_shuffle VR128:$src, (undef), + MOVDDUP_shuffle_mask)))]>; def MOVDDUPrm : S3DI<0x12, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), "movddup\t{$src, $dst|$dst, $src}", [(set VR128:$dst, - (v2f64 (movddup (scalar_to_vector (loadf64 addr:$src)), - (undef))))]>; - -def : Pat<(movddup (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src)))), - (undef)), + (v2f64 (vector_shuffle + (scalar_to_vector (loadf64 addr:$src)), + (undef), MOVDDUP_shuffle_mask)))]>; + +def : Pat<(vector_shuffle + (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src)))), + (undef), MOVDDUP_shuffle_mask), (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>; -def : Pat<(movddup (memopv2f64 addr:$src), (undef)), +def : Pat<(vector_shuffle + (memopv2f64 addr:$src), (undef), MOVDDUP_shuffle_mask), (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>; @@ -2499,18 +2555,22 @@ // vector_shuffle v1, <1, 1, 3, 3> let AddedComplexity = 15 in -def : Pat<(v4i32 (movshdup VR128:$src, (undef))), +def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), + MOVSHDUP_shuffle_mask)), (MOVSHDUPrr VR128:$src)>, Requires<[HasSSE3]>; let AddedComplexity = 20 in -def : Pat<(v4i32 (movshdup (bc_v4i32 (memopv2i64 addr:$src)), (undef))), +def : Pat<(v4i32 (vector_shuffle (bc_v4i32 (memopv2i64 addr:$src)), (undef), + MOVSHDUP_shuffle_mask)), (MOVSHDUPrm addr:$src)>, Requires<[HasSSE3]>; // vector_shuffle v1, <0, 0, 2, 2> let AddedComplexity = 15 in - def : Pat<(v4i32 (movsldup VR128:$src, (undef))), + def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), + MOVSLDUP_shuffle_mask)), (MOVSLDUPrr VR128:$src)>, Requires<[HasSSE3]>; let AddedComplexity = 20 in - def : Pat<(v4i32 (movsldup (bc_v4i32 (memopv2i64 addr:$src)), (undef))), + def : Pat<(v4i32 (vector_shuffle (bc_v4i32 (memopv2i64 addr:$src)), (undef), + MOVSLDUP_shuffle_mask)), (MOVSLDUPrm addr:$src)>, Requires<[HasSSE3]>; //===----------------------------------------------------------------------===// @@ -2851,173 +2911,207 @@ // Splat v2f64 / v2i64 let AddedComplexity = 10 in { -def : Pat<(splat_lo (v2f64 VR128:$src), (undef)), +def : Pat<(vector_shuffle (v2f64 VR128:$src), (undef), SSE_splat_lo_mask:$sm), (UNPCKLPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(unpckh (v2f64 VR128:$src), (undef)), +def : Pat<(vector_shuffle (v2f64 VR128:$src), (undef), UNPCKH_shuffle_mask:$sm), (UNPCKHPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(splat_lo (v2i64 VR128:$src), (undef)), +def : Pat<(vector_shuffle (v2i64 VR128:$src), (undef), SSE_splat_lo_mask:$sm), (PUNPCKLQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(unpckh (v2i64 VR128:$src), (undef)), +def : Pat<(vector_shuffle (v2i64 VR128:$src), (undef), UNPCKH_shuffle_mask:$sm), (PUNPCKHQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; } // Special unary SHUFPSrri case. -def : Pat<(v4f32 (pshufd:$src3 VR128:$src1, (undef))), - (SHUFPSrri VR128:$src1, VR128:$src1, - (SHUFFLE_get_shuf_imm VR128:$src3))>, +def : Pat<(v4f32 (vector_shuffle VR128:$src1, (undef), + SHUFP_unary_shuffle_mask:$sm)), + (SHUFPSrri VR128:$src1, VR128:$src1, SHUFP_unary_shuffle_mask:$sm)>, Requires<[HasSSE1]>; -let AddedComplexity = 5 in -def : Pat<(v4f32 (pshufd:$src2 VR128:$src1, (undef))), - (PSHUFDri VR128:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>, - Requires<[HasSSE2]>; -// Special unary SHUFPDrri case. -def : Pat<(v2i64 (pshufd:$src3 VR128:$src1, (undef))), - (SHUFPDrri VR128:$src1, VR128:$src1, - (SHUFFLE_get_shuf_imm VR128:$src3))>, - Requires<[HasSSE2]>; // Special unary SHUFPDrri case. -def : Pat<(v2f64 (pshufd:$src3 VR128:$src1, (undef))), - (SHUFPDrri VR128:$src1, VR128:$src1, - (SHUFFLE_get_shuf_imm VR128:$src3))>, +def : Pat<(v2f64 (vector_shuffle VR128:$src1, (undef), + SHUFP_unary_shuffle_mask:$sm)), + (SHUFPDrri VR128:$src1, VR128:$src1, SHUFP_unary_shuffle_mask:$sm)>, Requires<[HasSSE2]>; // Unary v4f32 shuffle with PSHUF* in order to fold a load. -def : Pat<(pshufd:$src2 (bc_v4i32 (memopv4f32 addr:$src1)), (undef)), - (PSHUFDmi addr:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>, +def : Pat<(vector_shuffle (bc_v4i32 (memopv4f32 addr:$src1)), (undef), + SHUFP_unary_shuffle_mask:$sm), + (PSHUFDmi addr:$src1, SHUFP_unary_shuffle_mask:$sm)>, Requires<[HasSSE2]>; // Special binary v4i32 shuffle cases with SHUFPS. -def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (v4i32 VR128:$src2))), - (SHUFPSrri VR128:$src1, VR128:$src2, - (SHUFFLE_get_shuf_imm VR128:$src3))>, +def : Pat<(v4i32 (vector_shuffle VR128:$src1, (v4i32 VR128:$src2), + PSHUFD_binary_shuffle_mask:$sm)), + (SHUFPSrri VR128:$src1, VR128:$src2, PSHUFD_binary_shuffle_mask:$sm)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (bc_v4i32 (memopv2i64 addr:$src2)))), - (SHUFPSrmi VR128:$src1, addr:$src2, - (SHUFFLE_get_shuf_imm VR128:$src3))>, +def : Pat<(v4i32 (vector_shuffle VR128:$src1, + (bc_v4i32 (memopv2i64 addr:$src2)), PSHUFD_binary_shuffle_mask:$sm)), + (SHUFPSrmi VR128:$src1, addr:$src2, PSHUFD_binary_shuffle_mask:$sm)>, Requires<[HasSSE2]>; // Special binary v2i64 shuffle cases using SHUFPDrri. -def : Pat<(v2i64 (shufp:$src3 VR128:$src1, VR128:$src2)), - (SHUFPDrri VR128:$src1, VR128:$src2, - (SHUFFLE_get_shuf_imm VR128:$src3))>, +def : Pat<(v2i64 (vector_shuffle VR128:$src1, VR128:$src2, + SHUFP_shuffle_mask:$sm)), + (SHUFPDrri VR128:$src1, VR128:$src2, SHUFP_shuffle_mask:$sm)>, Requires<[HasSSE2]>; +// Special unary SHUFPDrri case. +def : Pat<(v2i64 (vector_shuffle VR128:$src1, (undef), + SHUFP_unary_shuffle_mask:$sm)), + (SHUFPDrri VR128:$src1, VR128:$src1, SHUFP_unary_shuffle_mask:$sm)>, + Requires<[HasSSE2]>; // vector_shuffle v1, , <0, 0, 1, 1, ...> let AddedComplexity = 15 in { -def : Pat<(v4i32 (unpckl_undef:$src2 VR128:$src, (undef))), - (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, +def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), + UNPCKL_v_undef_shuffle_mask:$sm)), + (PSHUFDri VR128:$src, PSHUFD_shuffle_mask:$sm)>, Requires<[OptForSpeed, HasSSE2]>; -def : Pat<(v4f32 (unpckl_undef:$src2 VR128:$src, (undef))), - (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, +def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), + UNPCKL_v_undef_shuffle_mask:$sm)), + (PSHUFDri VR128:$src, PSHUFD_shuffle_mask:$sm)>, Requires<[OptForSpeed, HasSSE2]>; } let AddedComplexity = 10 in { -def : Pat<(v4f32 (unpckl_undef VR128:$src, (undef))), +def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), + UNPCKL_v_undef_shuffle_mask)), (UNPCKLPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; -def : Pat<(v16i8 (unpckl_undef VR128:$src, (undef))), +def : Pat<(v16i8 (vector_shuffle VR128:$src, (undef), + UNPCKL_v_undef_shuffle_mask)), (PUNPCKLBWrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(v8i16 (unpckl_undef VR128:$src, (undef))), +def : Pat<(v8i16 (vector_shuffle VR128:$src, (undef), + UNPCKL_v_undef_shuffle_mask)), (PUNPCKLWDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (unpckl_undef VR128:$src, (undef))), +def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), + UNPCKL_v_undef_shuffle_mask)), (PUNPCKLDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; } // vector_shuffle v1, , <2, 2, 3, 3, ...> let AddedComplexity = 15 in { -def : Pat<(v4i32 (unpckh_undef:$src2 VR128:$src, (undef))), - (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, +def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), + UNPCKH_v_undef_shuffle_mask:$sm)), + (PSHUFDri VR128:$src, PSHUFD_shuffle_mask:$sm)>, Requires<[OptForSpeed, HasSSE2]>; -def : Pat<(v4f32 (unpckh_undef:$src2 VR128:$src, (undef))), - (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, +def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), + UNPCKH_v_undef_shuffle_mask:$sm)), + (PSHUFDri VR128:$src, PSHUFD_shuffle_mask:$sm)>, Requires<[OptForSpeed, HasSSE2]>; } let AddedComplexity = 10 in { -def : Pat<(v4f32 (unpckh_undef VR128:$src, (undef))), +def : Pat<(v4f32 (vector_shuffle VR128:$src, (undef), + UNPCKH_v_undef_shuffle_mask)), (UNPCKHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; -def : Pat<(v16i8 (unpckh_undef VR128:$src, (undef))), +def : Pat<(v16i8 (vector_shuffle VR128:$src, (undef), + UNPCKH_v_undef_shuffle_mask)), (PUNPCKHBWrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(v8i16 (unpckh_undef VR128:$src, (undef))), +def : Pat<(v8i16 (vector_shuffle VR128:$src, (undef), + UNPCKH_v_undef_shuffle_mask)), (PUNPCKHWDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (unpckh_undef VR128:$src, (undef))), +def : Pat<(v4i32 (vector_shuffle VR128:$src, (undef), + UNPCKH_v_undef_shuffle_mask)), (PUNPCKHDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; } let AddedComplexity = 20 in { // vector_shuffle v1, v2 <0, 1, 4, 5> using MOVLHPS -def : Pat<(v4i32 (movhp VR128:$src1, VR128:$src2)), +def : Pat<(v4i32 (vector_shuffle VR128:$src1, VR128:$src2, + MOVHP_shuffle_mask)), (MOVLHPSrr VR128:$src1, VR128:$src2)>; // vector_shuffle v1, v2 <6, 7, 2, 3> using MOVHLPS -def : Pat<(v4i32 (movhlps VR128:$src1, VR128:$src2)), +def : Pat<(v4i32 (vector_shuffle VR128:$src1, VR128:$src2, + MOVHLPS_shuffle_mask)), (MOVHLPSrr VR128:$src1, VR128:$src2)>; // vector_shuffle v1, undef <2, ?, ?, ?> using MOVHLPS -def : Pat<(v4f32 (movhlps_undef VR128:$src1, (undef))), +def : Pat<(v4f32 (vector_shuffle VR128:$src1, (undef), + MOVHLPS_v_undef_shuffle_mask)), (MOVHLPSrr VR128:$src1, VR128:$src1)>; -def : Pat<(v4i32 (movhlps_undef VR128:$src1, (undef))), +def : Pat<(v4i32 (vector_shuffle VR128:$src1, (undef), + MOVHLPS_v_undef_shuffle_mask)), (MOVHLPSrr VR128:$src1, VR128:$src1)>; } let AddedComplexity = 20 in { // vector_shuffle v1, (load v2) <4, 5, 2, 3> using MOVLPS // vector_shuffle v1, (load v2) <0, 1, 4, 5> using MOVHPS -def : Pat<(v4f32 (movlp VR128:$src1, (load addr:$src2))), +def : Pat<(v4f32 (vector_shuffle VR128:$src1, (load addr:$src2), + MOVLP_shuffle_mask)), (MOVLPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE1]>; -def : Pat<(v2f64 (movlp VR128:$src1, (load addr:$src2))), +def : Pat<(v2f64 (vector_shuffle VR128:$src1, (load addr:$src2), + MOVLP_shuffle_mask)), (MOVLPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4f32 (movhp VR128:$src1, (load addr:$src2))), +def : Pat<(v4f32 (vector_shuffle VR128:$src1, (load addr:$src2), + MOVHP_shuffle_mask)), (MOVHPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE1]>; -def : Pat<(v2f64 (movhp VR128:$src1, (load addr:$src2))), +def : Pat<(v2f64 (vector_shuffle VR128:$src1, (load addr:$src2), + MOVHP_shuffle_mask)), (MOVHPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (movlp VR128:$src1, (load addr:$src2))), +def : Pat<(v4i32 (vector_shuffle VR128:$src1, (load addr:$src2), + MOVLP_shuffle_mask)), (MOVLPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v2i64 (movlp VR128:$src1, (load addr:$src2))), +def : Pat<(v2i64 (vector_shuffle VR128:$src1, (load addr:$src2), + MOVLP_shuffle_mask)), (MOVLPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (movhp VR128:$src1, (load addr:$src2))), +def : Pat<(v4i32 (vector_shuffle VR128:$src1, (load addr:$src2), + MOVHP_shuffle_mask)), (MOVHPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE1]>; -def : Pat<(v2i64 (movhp VR128:$src1, (load addr:$src2))), +def : Pat<(v2i64 (vector_shuffle VR128:$src1, (load addr:$src2), + MOVHP_shuffle_mask)), (MOVHPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; } // (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS // (store (vector_shuffle (load addr), v2, <0, 1, 4, 5>), addr) using MOVHPS -def : Pat<(store (v4f32 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), +def : Pat<(store (v4f32 (vector_shuffle (load addr:$src1), VR128:$src2, + MOVLP_shuffle_mask)), addr:$src1), (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; -def : Pat<(store (v2f64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), +def : Pat<(store (v2f64 (vector_shuffle (load addr:$src1), VR128:$src2, + MOVLP_shuffle_mask)), addr:$src1), (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(store (v4f32 (movhp (load addr:$src1), VR128:$src2)), addr:$src1), +def : Pat<(store (v4f32 (vector_shuffle (load addr:$src1), VR128:$src2, + MOVHP_shuffle_mask)), addr:$src1), (MOVHPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; -def : Pat<(store (v2f64 (movhp (load addr:$src1), VR128:$src2)), addr:$src1), +def : Pat<(store (v2f64 (vector_shuffle (load addr:$src1), VR128:$src2, + MOVHP_shuffle_mask)), addr:$src1), (MOVHPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(store (v4i32 (movlp (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)), - addr:$src1), +def : Pat<(store (v4i32 (vector_shuffle + (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2, + MOVLP_shuffle_mask)), addr:$src1), (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; -def : Pat<(store (v2i64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), +def : Pat<(store (v2i64 (vector_shuffle (load addr:$src1), VR128:$src2, + MOVLP_shuffle_mask)), addr:$src1), (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(store (v4i32 (movhp (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)), - addr:$src1), +def : Pat<(store (v4i32 (vector_shuffle + (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2, + MOVHP_shuffle_mask)), addr:$src1), (MOVHPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; -def : Pat<(store (v2i64 (movhp (load addr:$src1), VR128:$src2)), addr:$src1), +def : Pat<(store (v2i64 (vector_shuffle (load addr:$src1), VR128:$src2, + MOVHP_shuffle_mask)), addr:$src1), (MOVHPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; let AddedComplexity = 15 in { // Setting the lowest element in the vector. -def : Pat<(v4i32 (movl VR128:$src1, VR128:$src2)), +def : Pat<(v4i32 (vector_shuffle VR128:$src1, VR128:$src2, + MOVL_shuffle_mask)), (MOVLPSrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v2i64 (movl VR128:$src1, VR128:$src2)), +def : Pat<(v2i64 (vector_shuffle VR128:$src1, VR128:$src2, + MOVL_shuffle_mask)), (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; // vector_shuffle v1, v2 <4, 5, 2, 3> using MOVLPDrr (movsd) -def : Pat<(v4f32 (movlp VR128:$src1, VR128:$src2)), +def : Pat<(v4f32 (vector_shuffle VR128:$src1, VR128:$src2, + MOVLP_shuffle_mask)), (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (movlp VR128:$src1, VR128:$src2)), +def : Pat<(v4i32 (vector_shuffle VR128:$src1, VR128:$src2, + MOVLP_shuffle_mask)), (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; } // Set lowest element and zero upper elements. let AddedComplexity = 15 in -def : Pat<(v2f64 (movl immAllZerosV_bc, VR128:$src)), +def : Pat<(v2f64 (vector_shuffle immAllZerosV_bc, VR128:$src, + MOVL_shuffle_mask)), (MOVZPQILo2PQIrr VR128:$src)>, Requires<[HasSSE2]>; def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))), (MOVZPQILo2PQIrr VR128:$src)>, Requires<[HasSSE2]>; Modified: llvm/trunk/test/CodeGen/X86/vec_clear.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_clear.ll?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_clear.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_clear.ll Fri Apr 24 07:40:33 2009 @@ -1,7 +1,5 @@ -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin -o %t -f -; RUN: not grep and %t -; RUN: not grep psrldq %t -; RUN: grep xorps %t +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin | not grep and +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin | grep psrldq define <4 x float> @test(<4 x float>* %v1) nounwind { %tmp = load <4 x float>* %v1 ; <<4 x float>> [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_shuffle-10.ll Fri Apr 24 07:40:33 2009 @@ -1,7 +1,9 @@ -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -o %t -f -; RUN: grep unpcklps %t | count 1 -; RUN: grep pshufd %t | count 1 -; RUN: not grep {sub.*esp} %t +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | \ +; RUN: grep unpcklps | count 1 +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | \ +; RUN: grep unpckhps | count 1 +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | \ +; RUN: not grep {sub.*esp} define void @test(<4 x float>* %res, <4 x float>* %A, <4 x float>* %B) { %tmp = load <4 x float>* %B ; <<4 x float>> [#uses=2] Modified: llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_shuffle-16.ll Fri Apr 24 07:40:33 2009 @@ -1,10 +1,8 @@ -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse,-sse2 -mtriple=i386-apple-darwin -o %t -f -; RUN: grep shufps %t | count 4 -; RUN: grep movaps %t | count 2 -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin -o %t -f -; RUN: grep pshufd %t | count 4 -; RUN: not grep shufps %t -; RUN: not grep mov %t +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse,-sse2 | grep shufps | count 4 +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse,-sse2 -mtriple=i386-apple-darwin | grep mov | count 2 +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | grep pshufd | count 4 +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | not grep shufps +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -mtriple=i386-apple-darwin | not grep mov define <4 x float> @t1(<4 x float> %a, <4 x float> %b) nounwind { %tmp1 = shufflevector <4 x float> %b, <4 x float> undef, <4 x i32> zeroinitializer Modified: llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_shuffle-30.ll Fri Apr 24 07:40:33 2009 @@ -1,7 +1,8 @@ ; RUN: llvm-as < %s | llc -march=x86 -mattr=sse41 -disable-mmx -o %t -f ; RUN: grep pshufhw %t | grep 161 | count 1 -; RUN: grep shufps %t | count 1 -; RUN: not grep pslldq %t +; RUN: grep pslldq %t | count 1 + + ; Test case when creating pshufhw, we incorrectly set the higher order bit ; for an undef, @@ -19,4 +20,4 @@ %0 = shufflevector <4 x i32> %in, <4 x i32> , <4 x i32> < i32 undef, i32 5, i32 undef, i32 2> store <4 x i32> %0, <4 x i32>* %dest ret void -} +} \ No newline at end of file Modified: llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_shuffle-31.ll Fri Apr 24 07:40:33 2009 @@ -1,6 +1,6 @@ ; RUN: llvm-as < %s | llc -march=x86 -mcpu=yonah -o %t -f ; RUN: grep pextrw %t | count 1 -; RUN: grep movlhps %t | count 1 +; RUN: grep punpcklqdq %t | count 1 ; RUN: grep pshufhw %t | count 1 ; RUN: grep pinsrw %t | count 1 ; RUN: llvm-as < %s | llc -march=x86 -mcpu=core2 -o %t -f Modified: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp (original) +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp Fri Apr 24 07:40:33 2009 @@ -194,6 +194,10 @@ ConstraintType = SDTCisOpSmallerThanOp; x.SDTCisOpSmallerThanOp_Info.BigOperandNum = R->getValueAsInt("BigOperandNum"); + } else if (R->isSubClassOf("SDTCisIntVectorOfSameSize")) { + ConstraintType = SDTCisIntVectorOfSameSize; + x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum = + R->getValueAsInt("OtherOpNum"); } else if (R->isSubClassOf("SDTCisEltOfVec")) { ConstraintType = SDTCisEltOfVec; x.SDTCisEltOfVec_Info.OtherOperandNum = @@ -361,9 +365,23 @@ } return MadeChange; } + case SDTCisIntVectorOfSameSize: { + TreePatternNode *OtherOperand = + getOperandNum(x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum, + N, NumResults); + if (OtherOperand->hasTypeSet()) { + if (!isVector(OtherOperand->getTypeNum(0))) + TP.error(N->getOperator()->getName() + " VT operand must be a vector!"); + MVT IVT = OtherOperand->getTypeNum(0); + unsigned NumElements = IVT.getVectorNumElements(); + IVT = MVT::getIntVectorWithNumElements(NumElements); + return NodeToApply->UpdateNodeType(IVT.getSimpleVT(), TP); + } + return false; + } case SDTCisEltOfVec: { TreePatternNode *OtherOperand = - getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, + getOperandNum(x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum, N, NumResults); if (OtherOperand->hasTypeSet()) { if (!isVector(OtherOperand->getTypeNum(0))) @@ -907,6 +925,25 @@ if (NI.getNumResults() == 0) MadeChange |= UpdateNodeType(MVT::isVoid, TP); + // If this is a vector_shuffle operation, apply types to the build_vector + // operation. The types of the integers don't matter, but this ensures they + // won't get checked. + if (getOperator()->getName() == "vector_shuffle" && + getChild(2)->getOperator()->getName() == "build_vector") { + TreePatternNode *BV = getChild(2); + const std::vector &LegalVTs + = CDP.getTargetInfo().getLegalValueTypes(); + MVT::SimpleValueType LegalIntVT = MVT::Other; + for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i) + if (isInteger(LegalVTs[i]) && !isVector(LegalVTs[i])) { + LegalIntVT = LegalVTs[i]; + break; + } + assert(LegalIntVT != MVT::Other && "No legal integer VT?"); + + for (unsigned i = 0, e = BV->getNumChildren(); i != e; ++i) + MadeChange |= BV->getChild(i)->UpdateNodeType(LegalIntVT, TP); + } return MadeChange; } else if (getOperator()->isSubClassOf("Instruction")) { const DAGInstruction &Inst = CDP.getInstruction(getOperator()); @@ -2049,9 +2086,6 @@ IterateInference |= Result->getTree(0)-> UpdateNodeType(Pattern->getTree(0)->getExtTypes(), *Result); } while (IterateInference); - - // Blah? - Result->getTree(0)->setTransformFn(Pattern->getTree(0)->getTransformFn()); // Verify that we inferred enough types that we can do something with the // pattern and result. If these fire the user has to add type casts. Modified: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h?rev=69967&r1=69966&r2=69967&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h (original) +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h Fri Apr 24 07:40:33 2009 @@ -62,7 +62,8 @@ unsigned OperandNo; // The operand # this constraint applies to. enum { SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisSameAs, - SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec + SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisIntVectorOfSameSize, + SDTCisEltOfVec } ConstraintType; union { // The discriminated union. @@ -80,6 +81,9 @@ } SDTCisOpSmallerThanOp_Info; struct { unsigned OtherOperandNum; + } SDTCisIntVectorOfSameSize_Info; + struct { + unsigned OtherOperandNum; } SDTCisEltOfVec_Info; } x; From espindola at google.com Fri Apr 24 07:40:54 2009 From: espindola at google.com (Rafael Espindola) Date: Fri, 24 Apr 2009 13:40:54 +0100 Subject: [llvm-commits] [llvm] r69952 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/CellSPU/ lib/Target/PowerPC/ lib/Target/X86/ test/CodeGen/X86/ utils/TableGen/ In-Reply-To: <200904241124.51230.duncan.sands@math.u-psud.fr> References: <200904240343.n3O3h13J001960@zion.cs.uiuc.edu> <200904241124.51230.duncan.sands@math.u-psud.fr> Message-ID: <38a0d8450904240540v601c2d8au8532061f466ae388@mail.gmail.com> 2009/4/24 Duncan Sands : > Hi Nate, I'm seeing these testsuite failures on x86-64 linux: I reverted the patch for now. Cheers, -- Rafael Avila de Espindola Google | Gordon House | Barrow Street | Dublin 4 | Ireland Registered in Dublin, Ireland | Registration Number: 368047 From rafael.espindola at gmail.com Fri Apr 24 08:00:02 2009 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Fri, 24 Apr 2009 13:00:02 -0000 Subject: [llvm-commits] [llvm] r69968 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/2009-04-24.ll Message-ID: <200904241300.n3OD0Nhq031169@zion.cs.uiuc.edu> Author: rafael Date: Fri Apr 24 07:59:40 2009 New Revision: 69968 URL: http://llvm.org/viewvc/llvm-project?rev=69968&view=rev Log: Fix PR 4004 by including the call to __tls_get_addr in X86tlsaddr. This is not very elegant, but neither is the tls specification :-( Added: llvm/trunk/test/CodeGen/X86/2009-04-24.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86Instr64bit.td llvm/trunk/lib/Target/X86/X86InstrInfo.td Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=69968&r1=69967&r2=69968&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Apr 24 07:59:40 2009 @@ -4745,7 +4745,7 @@ static SDValue GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, - SDValue *InFlag) { + SDValue *InFlag, const MVT PtrVT, unsigned ReturnReg) { SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); DebugLoc dl = GA->getDebugLoc(); SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), @@ -4753,11 +4753,13 @@ GA->getOffset()); if (InFlag) { SDValue Ops[] = { Chain, TGA, *InFlag }; - return DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 3); + Chain = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 3); } else { SDValue Ops[] = { Chain, TGA }; - return DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 2); + Chain = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 2); } + SDValue Flag = Chain.getValue(1); + return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Flag); } // Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit @@ -4772,42 +4774,14 @@ PtrVT), InFlag); InFlag = Chain.getValue(1); - Chain = GetTLSADDR(DAG, Chain, GA, &InFlag); - InFlag = Chain.getValue(1); - - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); - SDValue Ops1[] = { Chain, - DAG.getTargetExternalSymbol("___tls_get_addr", - PtrVT), - DAG.getRegister(X86::EAX, PtrVT), - DAG.getRegister(X86::EBX, PtrVT), - InFlag }; - Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops1, 5); - InFlag = Chain.getValue(1); - - return DAG.getCopyFromReg(Chain, dl, X86::EAX, PtrVT, InFlag); + return GetTLSADDR(DAG, Chain, GA, &InFlag, PtrVT, X86::EAX); } // Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit static SDValue LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG, const MVT PtrVT) { - SDValue InFlag, Chain; - DebugLoc dl = GA->getDebugLoc(); // ? function entry point might be better - - Chain = GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL); - InFlag = Chain.getValue(1); - - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); - SDValue Ops1[] = { Chain, - DAG.getTargetExternalSymbol("__tls_get_addr", - PtrVT), - DAG.getRegister(X86::RDI, PtrVT), - InFlag }; - Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops1, 4); - InFlag = Chain.getValue(1); - - return DAG.getCopyFromReg(Chain, dl, X86::RAX, PtrVT, InFlag); + return GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL, PtrVT, X86::RAX); } // Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or Modified: llvm/trunk/lib/Target/X86/X86Instr64bit.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Instr64bit.td?rev=69968&r1=69967&r2=69968&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Fri Apr 24 07:59:40 2009 @@ -1303,9 +1303,17 @@ // Thread Local Storage Instructions //===----------------------------------------------------------------------===// -let hasSideEffects = 1, Defs = [RDI] in +// All calls clobber the non-callee saved registers. RSP is marked as +// a use to prevent stack-pointer assignments that appear immediately +// before calls from potentially appearing dead. +let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, + FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], + Uses = [RSP] in def TLS_addr64 : I<0, Pseudo, (outs), (ins i64imm:$sym), - ".byte\t0x66; leaq\t${sym:mem}(%rip), %rdi; .word\t0x6666; rex64", + ".byte\t0x66; leaq\t${sym:mem}(%rip), %rdi; .word\t0x6666; rex64;call\t__tls_get_addr at PLT", [(X86tlsaddr tglobaltlsaddr:$sym)]>, Requires<[In64BitMode]>; Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=69968&r1=69967&r2=69968&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Fri Apr 24 07:59:40 2009 @@ -2977,9 +2977,16 @@ // Thread Local Storage Instructions // -let hasSideEffects = 1, Uses = [EBX], Defs = [EAX] in +// All calls clobber the non-callee saved registers. ESP is marked as +// a use to prevent stack-pointer assignments that appear immediately +// before calls from potentially appearing dead. +let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], + Uses = [ESP, EBX] in def TLS_addr32 : I<0, Pseudo, (outs), (ins i32imm:$sym), - "leal\t${sym:mem}(,%ebx,1), %eax", + "leal\t${sym:mem}(,%ebx,1), %eax; call\t___tls_get_addr at PLT", [(X86tlsaddr tglobaltlsaddr:$sym)]>, Requires<[In32BitMode]>; Added: llvm/trunk/test/CodeGen/X86/2009-04-24.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-04-24.ll?rev=69968&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/2009-04-24.ll (added) +++ llvm/trunk/test/CodeGen/X86/2009-04-24.ll Fri Apr 24 07:59:40 2009 @@ -0,0 +1,13 @@ +; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu -regalloc=local -relocation-model=pic > %t +; RUN: grep {leal.*TLSGD.*___tls_get_addr} %t +; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu -regalloc=local -relocation-model=pic > %t2 +; RUN: grep {leaq.*TLSGD.*__tls_get_addr} %t2 +; PR/4004 + + at i = thread_local global i32 15 + +define i32 @f() { +entry: + %tmp1 = load i32* @i + ret i32 %tmp1 +} From baldrick at free.fr Fri Apr 24 09:29:19 2009 From: baldrick at free.fr (Duncan Sands) Date: Fri, 24 Apr 2009 16:29:19 +0200 Subject: [llvm-commits] [llvm] r69946 - in /llvm/trunk: docs/LangRef.html lib/Transforms/Scalar/InstructionCombining.cpp lib/VMCore/Type.cpp In-Reply-To: <200904240237.n3O2bsqj032157@zion.cs.uiuc.edu> References: <200904240237.n3O2bsqj032157@zion.cs.uiuc.edu> Message-ID: <200904241629.20154.baldrick@free.fr> Hi Sanjiv, > -only integers of 32 or 64 bits are allowed (also non-constants). 32-bit values > +only integers of 16, 32 or 64 bits are allowed (also non-constants).16-bit Missing space between the . and 16. Also, there is a trailing space on this line, and doubled spaces in the next line: > +values will be sign extended to 32-bits if required, and 32-bit values > %eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1 > + ; yields i16*:iptr > + %iptr = getelementptr [10 x i16]* @arr, i16 0, i16 0 I think it's confusing to have both the index and the array involve i16's: people might think that there's some kind of connection between have an i16 pointer and an i16 index. Ciao, Duncan. From sanjiv.gupta at microchip.com Fri Apr 24 11:38:26 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Fri, 24 Apr 2009 16:38:26 -0000 Subject: [llvm-commits] [llvm] r69971 - /llvm/trunk/docs/LangRef.html Message-ID: <200904241638.n3OGcRFx006947@zion.cs.uiuc.edu> Author: sgupta Date: Fri Apr 24 11:38:13 2009 New Revision: 69971 URL: http://llvm.org/viewvc/llvm-project?rev=69971&view=rev Log: Fixed spaces and the getelementpointer example with i16 type indices. Modified: llvm/trunk/docs/LangRef.html Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=69971&r1=69970&r2=69971&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Fri Apr 24 11:38:13 2009 @@ -3629,8 +3629,8 @@

The type of each index argument depends on the type it is indexing into. When indexing into a (packed) structure, only i32 integer constants are allowed. When indexing into an array, pointer or vector, -only integers of 16, 32 or 64 bits are allowed (also non-constants).16-bit -values will be sign extended to 32-bits if required, and 32-bit values +only integers of 16, 32 or 64 bits are allowed (also non-constants). 16-bit +values will be sign extended to 32-bits if required, and 32-bit values will be sign extended to 64-bits if required.

For example, let's consider a C code fragment and how it gets @@ -3719,7 +3719,7 @@ ; yields i8*:eptr %eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1 ; yields i16*:iptr - %iptr = getelementptr [10 x i16]* @arr, i16 0, i16 0 + %iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0

From bob.wilson at apple.com Fri Apr 24 11:55:36 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Fri, 24 Apr 2009 16:55:36 -0000 Subject: [llvm-commits] [llvm] r69973 - /llvm/trunk/lib/Target/ARM/ARMCallingConv.td Message-ID: <200904241655.n3OGtbr5008160@zion.cs.uiuc.edu> Author: bwilson Date: Fri Apr 24 11:55:25 2009 New Revision: 69973 URL: http://llvm.org/viewvc/llvm-project?rev=69973&view=rev Log: Remove unnecessary references to f32 types. After specifying that f32 should be bit-converted to i32, it is sufficient to list only i32 in subsequent definitions. Modified: llvm/trunk/lib/Target/ARM/ARMCallingConv.td Modified: llvm/trunk/lib/Target/ARM/ARMCallingConv.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMCallingConv.td?rev=69973&r1=69972&r2=69973&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMCallingConv.td (original) +++ llvm/trunk/lib/Target/ARM/ARMCallingConv.td Fri Apr 24 11:55:25 2009 @@ -28,9 +28,9 @@ CCIfType<[f64], CCCustom<"CC_ARM_APCS_Custom_f64">>, CCIfType<[f32], CCBitConvertToType>, - CCIfType<[i32, f32], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, + CCIfType<[i32], CCAssignToStack<4, 4>>, CCIfType<[f64], CCAssignToStack<8, 4>> ]>; @@ -55,9 +55,9 @@ CCIfType<[f64], CCCustom<"CC_ARM_AAPCS_Custom_f64">>, CCIfType<[f32], CCBitConvertToType>, - CCIfType<[i32, f32], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, + CCIfType<[i32], CCAssignToStack<4, 4>>, CCIfType<[f64], CCAssignToStack<8, 8>> ]>; From rafael.espindola at gmail.com Fri Apr 24 11:55:36 2009 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Fri, 24 Apr 2009 16:55:36 -0000 Subject: [llvm-commits] [llvm] r69972 - in /llvm/trunk: include/llvm-c/lto.h tools/gold/gold-plugin.cpp tools/lto/LTOModule.cpp tools/lto/LTOModule.h Message-ID: <200904241655.n3OGtc1e008165@zion.cs.uiuc.edu> Author: rafael Date: Fri Apr 24 11:55:21 2009 New Revision: 69972 URL: http://llvm.org/viewvc/llvm-project?rev=69972&view=rev Log: Add LTO_SYMBOL_DEFINITION_WEAKUNDEF, use that on the gold plugin. Modified: llvm/trunk/include/llvm-c/lto.h llvm/trunk/tools/gold/gold-plugin.cpp llvm/trunk/tools/lto/LTOModule.cpp llvm/trunk/tools/lto/LTOModule.h Modified: llvm/trunk/include/llvm-c/lto.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/lto.h?rev=69972&r1=69971&r2=69972&view=diff ============================================================================== --- llvm/trunk/include/llvm-c/lto.h (original) +++ llvm/trunk/include/llvm-c/lto.h Fri Apr 24 11:55:21 2009 @@ -30,6 +30,7 @@ LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200, LTO_SYMBOL_DEFINITION_WEAK = 0x00000300, LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400, + LTO_SYMBOL_DEFINITION_WEAKUNDEF = 0x00000500, LTO_SYMBOL_SCOPE_MASK = 0x00003800, LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800, LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000, Modified: llvm/trunk/tools/gold/gold-plugin.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=69972&r1=69971&r2=69972&view=diff ============================================================================== --- llvm/trunk/tools/gold/gold-plugin.cpp (original) +++ llvm/trunk/tools/gold/gold-plugin.cpp Fri Apr 24 11:55:21 2009 @@ -257,6 +257,9 @@ case LTO_SYMBOL_DEFINITION_WEAK: sym.def = LDPK_WEAKDEF; break; + case LTO_SYMBOL_DEFINITION_WEAKUNDEF: + sym.def = LDPK_WEAKUNDEF; + break; default: (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition); return LDPS_ERR; Modified: llvm/trunk/tools/lto/LTOModule.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto/LTOModule.cpp?rev=69972&r1=69971&r2=69972&view=diff ============================================================================== --- llvm/trunk/tools/lto/LTOModule.cpp (original) +++ llvm/trunk/tools/lto/LTOModule.cpp Fri Apr 24 11:55:21 2009 @@ -258,9 +258,21 @@ { const char* name = mangler.getValueName(decl).c_str(); // ignore all llvm.* symbols - if ( strncmp(name, "llvm.", 5) != 0 ) { - _undefines[name] = 1; - } + if ( strncmp(name, "llvm.", 5) == 0 ) + return; + + // we already have the symbol + if (_undefines.find(name) != _undefines.end()) + return; + + NameAndAttributes info; + // string is owned by _undefines + info.name = ::strdup(name); + if (decl->hasExternalWeakLinkage()) + info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF; + else + info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + _undefines[name] = info; } @@ -339,16 +351,14 @@ } // make symbols for all undefines - for (StringSet::iterator it=_undefines.begin(); + for (StringMap::iterator it=_undefines.begin(); it != _undefines.end(); ++it) { // if this symbol also has a definition, then don't make an undefine // because it is a tentative definition if ( _defines.count(it->getKeyData(), it->getKeyData()+ it->getKeyLength()) == 0 ) { - NameAndAttributes info; - info.name = it->getKeyData(); - info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; - _symbols.push_back(info); + NameAndAttributes info = it->getValue(); + _symbols.push_back(info); } } } Modified: llvm/trunk/tools/lto/LTOModule.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto/LTOModule.h?rev=69972&r1=69971&r2=69972&view=diff ============================================================================== --- llvm/trunk/tools/lto/LTOModule.h (original) +++ llvm/trunk/tools/lto/LTOModule.h Fri Apr 24 11:55:21 2009 @@ -97,7 +97,7 @@ std::vector _symbols; // _defines and _undefines only needed to disambiguate tentative definitions StringSet _defines; - StringSet _undefines; + llvm::StringMap _undefines; }; extern std::string getFeatureString(const char *TargetTriple); From greened at obbligato.org Fri Apr 24 11:55:43 2009 From: greened at obbligato.org (David Greene) Date: Fri, 24 Apr 2009 16:55:43 -0000 Subject: [llvm-commits] [llvm] r69974 - in /llvm/trunk: test/TableGen/MultiClassInherit.td utils/TableGen/Record.cpp utils/TableGen/Record.h utils/TableGen/TGParser.cpp Message-ID: <200904241655.n3OGthFA008186@zion.cs.uiuc.edu> Author: greened Date: Fri Apr 24 11:55:41 2009 New Revision: 69974 URL: http://llvm.org/viewvc/llvm-project?rev=69974&view=rev Log: Fix multiclass inheritance to limit value resolution to new defs added by base multiclasses. Do not attempt to alter defs from previous base multiclasses. This fixes multiple multiclass inheritance. Modified: llvm/trunk/test/TableGen/MultiClassInherit.td llvm/trunk/utils/TableGen/Record.cpp llvm/trunk/utils/TableGen/Record.h llvm/trunk/utils/TableGen/TGParser.cpp Modified: llvm/trunk/test/TableGen/MultiClassInherit.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/MultiClassInherit.td?rev=69974&r1=69973&r2=69974&view=diff ============================================================================== --- llvm/trunk/test/TableGen/MultiClassInherit.td (original) +++ llvm/trunk/test/TableGen/MultiClassInherit.td Fri Apr 24 11:55:41 2009 @@ -1,4 +1,4 @@ -// RUN: tblgen %s | grep {zing = 4} | count 4 +// RUN: tblgen %s | grep {zing = 4} | count 28 class C1 { int bar = A; @@ -8,25 +8,57 @@ def T : C1<4, "blah">; -multiclass t { - def S1 : C1 { +multiclass t1 { + def S1 : C1 { int foo = 4; let bar = 1; } - def S2 : C1; + def S2 : C1; } -multiclass s : t
{ - def S3 : C1 { +multiclass t2 { + def S3 : C1 { + int foo = 4; + let bar = 1; + } + def S4 : C1; +} + +multiclass s1 : t1 { + def S5 : C1 { int moo = 3; let bar = 1; } - def S4 : C1; + def S6 : C1; } -defm FOO : s<42, 24>; +multiclass s2 : t1, t2; + +multiclass s3 : t1, t2 { + def S7 : C1 { + int moo = 3; + let bar = 1; + } + def S8 : C1; +} + +let zing = 4 in +defm FOO1 : s1<42, 24>; + +let zing = 4 in +defm FOO2 : s2<99>; + +let zing = 4 in +defm FOO3 : s3<84, 48>; def T4 : C1<6, "foo">; let zing = 4 in - defm BAZ : s<3, 4>; + defm BAZ1 : s1<3, 4>; + +let zing = 4 in + defm BAZ2 : s2<5>; + +let zing = 4 in + defm BAZ3 : s3<6, 7>; + Modified: llvm/trunk/utils/TableGen/Record.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.cpp?rev=69974&r1=69973&r2=69974&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/Record.cpp (original) +++ llvm/trunk/utils/TableGen/Record.cpp Fri Apr 24 11:55:41 2009 @@ -1060,6 +1060,20 @@ } +void MultiClass::dump() const { + cerr << "Record:\n"; + Rec.dump(); + + cerr << "Defs:\n"; + for (RecordVector::const_iterator r = DefPrototypes.begin(), + rend = DefPrototypes.end(); + r != rend; + ++r) { + (*r)->dump(); + } +} + + void RecordKeeper::dump() const { cerr << *this; } std::ostream &llvm::operator<<(std::ostream &OS, const RecordKeeper &RK) { Modified: llvm/trunk/utils/TableGen/Record.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.h?rev=69974&r1=69973&r2=69974&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/Record.h (original) +++ llvm/trunk/utils/TableGen/Record.h Fri Apr 24 11:55:41 2009 @@ -1138,7 +1138,9 @@ Record Rec; // Placeholder for template args and Name. typedef std::vector RecordVector; RecordVector DefPrototypes; - + + void dump() const; + MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {} }; Modified: llvm/trunk/utils/TableGen/TGParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.cpp?rev=69974&r1=69973&r2=69974&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/TGParser.cpp (original) +++ llvm/trunk/utils/TableGen/TGParser.cpp Fri Apr 24 11:55:41 2009 @@ -16,6 +16,7 @@ #include "TGParser.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Streams.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -28,7 +29,7 @@ Record *Rec; std::vector TemplateArgs; SubClassReference() : Rec(0) {} - + bool isInvalid() const { return Rec == 0; } }; @@ -39,8 +40,23 @@ SubMultiClassReference() : MC(0) {} bool isInvalid() const { return MC == 0; } + void dump() const; }; - + +void SubMultiClassReference::dump() const { + cerr << "Multiclass:\n"; + + MC->dump(); + + cerr << "Template args:\n"; + for (std::vector::const_iterator i = TemplateArgs.begin(), + iend = TemplateArgs.end(); + i != iend; + ++i) { + (*i)->dump(); + } +} + } // end namespace llvm bool TGParser::AddValue(Record *CurRec, TGLoc Loc, const RecordVal &RV) { @@ -182,7 +198,8 @@ /// AddSubMultiClass - Add SubMultiClass as a subclass to /// CurMultiClass, resolving its template args as SubMultiClass's /// template arguments. -bool TGParser::AddSubMultiClass(MultiClass *CurMultiClass, class SubMultiClassReference &SubMultiClass) { +bool TGParser::AddSubMultiClass(MultiClass *CurMultiClass, + class SubMultiClassReference &SubMultiClass) { MultiClass *SMC = SubMultiClass.MC; Record *CurRec = &CurMultiClass->Rec; @@ -194,6 +211,8 @@ if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i])) return true; + int newDefStart = CurMultiClass->DefPrototypes.size(); + // Add all of the defs in the subclass into the current multiclass. for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(), iend = SMC->DefPrototypes.end(); @@ -212,16 +231,20 @@ const std::vector &SMCTArgs = SMC->Rec.getTemplateArgs(); - // Ensure that an appropriate number of template arguments are specified. + // Ensure that an appropriate number of template arguments are + // specified. if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size()) - return Error(SubMultiClass.RefLoc, "More template args specified than expected"); + return Error(SubMultiClass.RefLoc, + "More template args specified than expected"); // Loop over all of the template arguments, setting them to the specified // value or leaving them as the default if necessary. for (unsigned i = 0, e = SMCTArgs.size(); i != e; ++i) { if (i < SubMultiClass.TemplateArgs.size()) { - // If a value is specified for this template arg, set it in the superclass now. - if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i], std::vector(), + // If a value is specified for this template arg, set it in the + // superclass now. + if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i], + std::vector(), SubMultiClass.TemplateArgs[i])) return true; @@ -231,14 +254,17 @@ // Now remove it. CurRec->removeValue(SMCTArgs[i]); - // If a value is specified for this template arg, set it in the defs now. - for (MultiClass::RecordVector::iterator j = CurMultiClass->DefPrototypes.begin(), + // If a value is specified for this template arg, set it in the + // new defs now. + for (MultiClass::RecordVector::iterator j = + CurMultiClass->DefPrototypes.begin() + newDefStart, jend = CurMultiClass->DefPrototypes.end(); j != jend; ++j) { Record *Def = *j; - if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], std::vector(), + if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], + std::vector(), SubMultiClass.TemplateArgs[i])) return true; @@ -249,7 +275,8 @@ Def->removeValue(SMCTArgs[i]); } } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) { - return Error(SubMultiClass.RefLoc,"Value not specified for template argument #" + return Error(SubMultiClass.RefLoc, + "Value not specified for template argument #" + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" + SMC->Rec.getName() + "'!"); } @@ -1490,8 +1517,12 @@ if (ParseTemplateArgList(0)) return true; + bool inherits = false; + // If there are submulticlasses, parse them. if (Lex.getCode() == tgtok::colon) { + inherits = true; + Lex.Lex(); // Read all of the submulticlasses. @@ -1510,17 +1541,25 @@ } } - if (Lex.getCode() != tgtok::l_brace) - return TokError("expected '{' in multiclass definition"); - - if (Lex.Lex() == tgtok::r_brace) // eat the '{'. - return TokError("multiclass must contain at least one def"); + if (Lex.getCode() != tgtok::l_brace) { + if (!inherits) + return TokError("expected '{' in multiclass definition"); + else + if (Lex.getCode() != tgtok::semi) + return TokError("expected ';' in multiclass definition"); + else + Lex.Lex(); // eat the ';'. + } + else { + if (Lex.Lex() == tgtok::r_brace) // eat the '{'. + return TokError("multiclass must contain at least one def"); - while (Lex.getCode() != tgtok::r_brace) - if (ParseMultiClassDef(CurMultiClass)) - return true; + while (Lex.getCode() != tgtok::r_brace) + if (ParseMultiClassDef(CurMultiClass)) + return true; - Lex.Lex(); // eat the '}'. + Lex.Lex(); // eat the '}'. + } CurMultiClass = 0; return false; From ggreif at gmail.com Fri Apr 24 12:00:03 2009 From: ggreif at gmail.com (Gabor Greif) Date: Fri, 24 Apr 2009 17:00:03 -0000 Subject: [llvm-commits] [llvm] r69976 - /llvm/trunk/Makefile Message-ID: <200904241700.n3OH03Ud008374@zion.cs.uiuc.edu> Author: ggreif Date: Fri Apr 24 12:00:03 2009 New Revision: 69976 URL: http://llvm.org/viewvc/llvm-project?rev=69976&view=rev Log: Use a bigger hammer to coerce subversion into english. Patch by Benjamin Kramer! Modified: llvm/trunk/Makefile Modified: llvm/trunk/Makefile URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/Makefile?rev=69976&r1=69975&r2=69976&view=diff ============================================================================== --- llvm/trunk/Makefile (original) +++ llvm/trunk/Makefile Fri Apr 24 12:00:03 2009 @@ -187,7 +187,7 @@ SVN-UPDATE-OPTIONS = AWK = awk SUB-SVN-DIRS = $(AWK) '/\?\ \ \ \ \ \ / {print $$2}' \ - | LANG=C xargs $(SVN) info 2>/dev/null \ + | LC_ALL=C xargs $(SVN) info 2>/dev/null \ | $(AWK) '/Path:\ / {print $$2}' update: From bob.wilson at apple.com Fri Apr 24 12:00:37 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Fri, 24 Apr 2009 17:00:37 -0000 Subject: [llvm-commits] [llvm] r69977 - /llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Message-ID: <200904241700.n3OH0bbq008413@zion.cs.uiuc.edu> Author: bwilson Date: Fri Apr 24 12:00:36 2009 New Revision: 69977 URL: http://llvm.org/viewvc/llvm-project?rev=69977&view=rev Log: Fix up some problems with getCopyToReg and getCopyFromReg nodes being chained and "flagged" together. I also made a few changes to handle the chain and flag values more consistently. I found these problems by inspection so I'm not aware of anything that breaks because of them (thus no testcase). 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=69977&r1=69976&r2=69977&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Apr 24 12:00:36 2009 @@ -504,23 +504,26 @@ if (VA.needsCustom()) { SDValue Lo = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), InFlag); + Chain = Lo.getValue(1); + InFlag = Lo.getValue(2); VA = RVLocs[++i]; // skip ahead to next loc - SDValue Hi = DAG.getCopyFromReg(Lo, dl, VA.getLocReg(), VA.getLocVT(), - Lo.getValue(2)); + SDValue Hi = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), + InFlag); + Chain = Hi.getValue(1); + InFlag = Hi.getValue(2); ResultVals.push_back(DAG.getNode(ARMISD::FMDRR, dl, VA.getValVT(), Lo, Hi)); } else { - Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), - InFlag).getValue(1); - SDValue Val = Chain.getValue(0); - InFlag = Chain.getValue(2); + SDValue Val = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), + InFlag); + Chain = Val.getValue(1); + InFlag = Val.getValue(2); switch (VA.getLocInfo()) { default: assert(0 && "Unknown loc info!"); case CCValAssign::Full: break; case CCValAssign::BCvt: - Val = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getValVT(), - Chain.getValue(0)); + Val = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getValVT(), Val); break; } @@ -813,6 +816,7 @@ SDValue fmrrd = DAG.getNode(ARMISD::FMRRD, dl, DAG.getVTList(MVT::i32, MVT::i32), &Arg, 1); Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), fmrrd, Flag); + Flag = Chain.getValue(1); VA = RVLocs[++i]; // skip ahead to next loc Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), fmrrd.getValue(1), Flag); From bob.wilson at apple.com Fri Apr 24 12:05:02 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Fri, 24 Apr 2009 17:05:02 -0000 Subject: [llvm-commits] [llvm] r69978 - /llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Message-ID: <200904241705.n3OH522F008599@zion.cs.uiuc.edu> Author: bwilson Date: Fri Apr 24 12:05:01 2009 New Revision: 69978 URL: http://llvm.org/viewvc/llvm-project?rev=69978&view=rev Log: Adjust a comment to reflect what the code does. Splitting a 64-bit argument between registers and the stack may be required with the APCS ABI, but it isn't tied to using a particular version of the ARM architecture. 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=69978&r1=69977&r2=69978&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Apr 24 12:05:01 2009 @@ -1103,7 +1103,7 @@ VA = ArgLocs[++i]; // skip ahead to next loc if (VA.isMemLoc()) { - // must be APCS and older than V5T to split like this + // must be APCS to split like this unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; int FI = MFI->CreateFixedObject(ArgSize, VA.getLocMemOffset()); From baldrick at free.fr Fri Apr 24 12:53:59 2009 From: baldrick at free.fr (Duncan Sands) Date: Fri, 24 Apr 2009 19:53:59 +0200 Subject: [llvm-commits] [llvm] r69971 - /llvm/trunk/docs/LangRef.html In-Reply-To: <200904241638.n3OGcRFx006947@zion.cs.uiuc.edu> References: <200904241638.n3OGcRFx006947@zion.cs.uiuc.edu> Message-ID: <200904241953.59660.baldrick@free.fr> Hi Sanjiv, > ; yields i16*:iptr Now yields i32*. > - %iptr = getelementptr [10 x i16]* @arr, i16 0, i16 0 > + %iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0 Ciao, Duncan. From bob.wilson at apple.com Fri Apr 24 15:53:42 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Fri, 24 Apr 2009 13:53:42 -0700 Subject: [llvm-commits] [llvm] r69978 - /llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp In-Reply-To: <200904241705.n3OH522F008599@zion.cs.uiuc.edu> References: <200904241705.n3OH522F008599@zion.cs.uiuc.edu> Message-ID: Upon further investigation.... The comment _did_ match the code, but I believe the code to be incorrect. There's not much point in reverting a change to a comment, but I'll be sure to put things back in a state where comment == code once I finish sorting this out. On Apr 24, 2009, at 10:05 AM, Bob Wilson wrote: > Author: bwilson > Date: Fri Apr 24 12:05:01 2009 > New Revision: 69978 > > URL: http://llvm.org/viewvc/llvm-project?rev=69978&view=rev > Log: > Adjust a comment to reflect what the code does. Splitting a 64-bit > argument > between registers and the stack may be required with the APCS ABI, > but it > isn't tied to using a particular version of the ARM architecture. > > 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=69978&r1=69977&r2=69978&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) > +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Apr 24 > 12:05:01 2009 > @@ -1103,7 +1103,7 @@ > > VA = ArgLocs[++i]; // skip ahead to next loc > if (VA.isMemLoc()) { > - // must be APCS and older than V5T to split like this > + // must be APCS to split like this > unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; > int FI = MFI->CreateFixedObject(ArgSize, > VA.getLocMemOffset()); > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From dalej at apple.com Fri Apr 24 16:34:14 2009 From: dalej at apple.com (Dale Johannesen) Date: Fri, 24 Apr 2009 21:34:14 -0000 Subject: [llvm-commits] [llvm] r69990 - in /llvm/trunk: lib/CodeGen/SelectionDAG/SelectionDAG.cpp test/CodeGen/Generic/fp-to-int-invalid.ll Message-ID: <200904242134.n3OLYEgh018732@zion.cs.uiuc.edu> Author: johannes Date: Fri Apr 24 16:34:13 2009 New Revision: 69990 URL: http://llvm.org/viewvc/llvm-project?rev=69990&view=rev Log: Fix PR 4057, a crash doing float->char const folding. This particular one is undefined behavior (although this isn't related to the crash), so it will no longer do it at compile time, which seems better. Added: llvm/trunk/test/CodeGen/Generic/fp-to-int-invalid.ll Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=69990&r1=69989&r2=69990&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Fri Apr 24 16:34:13 2009 @@ -2197,16 +2197,17 @@ } case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: { - integerPart x; + integerPart x[2]; bool ignored; assert(integerPartWidth >= 64); // FIXME need to be more flexible about rounding mode. - APFloat::opStatus s = V.convertToInteger(&x, 64U, + APFloat::opStatus s = V.convertToInteger(x, VT.getSizeInBits(), Opcode==ISD::FP_TO_SINT, APFloat::rmTowardZero, &ignored); if (s==APFloat::opInvalidOp) // inexact is OK, in fact usual break; - return getConstant(x, VT); + APInt api(VT.getSizeInBits(), 2, x); + return getConstant(api, VT); } case ISD::BIT_CONVERT: if (VT == MVT::i32 && C->getValueType(0) == MVT::f32) Added: llvm/trunk/test/CodeGen/Generic/fp-to-int-invalid.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Generic/fp-to-int-invalid.ll?rev=69990&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/Generic/fp-to-int-invalid.ll (added) +++ llvm/trunk/test/CodeGen/Generic/fp-to-int-invalid.ll Fri Apr 24 16:34:13 2009 @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | llc +; PR4057 +define void @test_cast_float_to_char(i8* %result) nounwind { +entry: + %result_addr = alloca i8* ; [#uses=2] + %test = alloca float ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i8* %result, i8** %result_addr + store float 0x40B2AFA160000000, float* %test, align 4 + %0 = load float* %test, align 4 ; [#uses=1] + %1 = fptosi float %0 to i8 ; [#uses=1] + %2 = load i8** %result_addr, align 4 ; [#uses=1] + store i8 %1, i8* %2, align 1 + br label %return + +return: ; preds = %entry + ret void +} From kremenek at apple.com Fri Apr 24 17:01:44 2009 From: kremenek at apple.com (Ted Kremenek) Date: Fri, 24 Apr 2009 22:01:44 -0000 Subject: [llvm-commits] [llvm] r69994 - /llvm/tags/checker/checker-0.189/ Message-ID: <200904242201.n3OM1iCc019676@zion.cs.uiuc.edu> Author: kremenek Date: Fri Apr 24 17:01:44 2009 New Revision: 69994 URL: http://llvm.org/viewvc/llvm-project?rev=69994&view=rev Log: Tagging checker-0.189. Added: llvm/tags/checker/checker-0.189/ - copied from r69993, llvm/trunk/ From nbegeman at apple.com Fri Apr 24 17:46:41 2009 From: nbegeman at apple.com (Nate Begeman) Date: Fri, 24 Apr 2009 15:46:41 -0700 Subject: [llvm-commits] [llvm] r69952 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/CellSPU/ lib/Target/PowerPC/ lib/Target/X86/ test/CodeGen/X86/ utils/TableGen/ Message-ID: Duncan / Rafael: What are you seeing for these tests that fail? I don't have a linux machine to test on, and none of the automated builders complained. Could you send the full output that doesn't match? Thanks, Nate From bob.wilson at apple.com Fri Apr 24 19:33:21 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Sat, 25 Apr 2009 00:33:21 -0000 Subject: [llvm-commits] [llvm] r70006 - /llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Message-ID: <200904250033.n3P0XL7C024187@zion.cs.uiuc.edu> Author: bwilson Date: Fri Apr 24 19:33:20 2009 New Revision: 70006 URL: http://llvm.org/viewvc/llvm-project?rev=70006&view=rev Log: Change LowerCallResult method so that CCValAssign::BCvt can be used with f64 types. This is not used for anything yet. 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=70006&r1=70005&r2=70006&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Apr 24 19:33:20 2009 @@ -500,35 +500,35 @@ for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign VA = RVLocs[i]; - // handle f64 as custom + SDValue Val; if (VA.needsCustom()) { - SDValue Lo = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), + // Handle f64 as custom. + SDValue Lo = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, InFlag); Chain = Lo.getValue(1); InFlag = Lo.getValue(2); VA = RVLocs[++i]; // skip ahead to next loc - SDValue Hi = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), + SDValue Hi = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, InFlag); Chain = Hi.getValue(1); InFlag = Hi.getValue(2); - ResultVals.push_back(DAG.getNode(ARMISD::FMDRR, dl, VA.getValVT(), Lo, - Hi)); + Val = DAG.getNode(ARMISD::FMDRR, dl, MVT::f64, Lo, Hi); } else { - SDValue Val = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), - InFlag); + Val = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), + InFlag); Chain = Val.getValue(1); InFlag = Val.getValue(2); + } - switch (VA.getLocInfo()) { - default: assert(0 && "Unknown loc info!"); - case CCValAssign::Full: break; - case CCValAssign::BCvt: - Val = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getValVT(), Val); - break; - } - - ResultVals.push_back(Val); + switch (VA.getLocInfo()) { + default: assert(0 && "Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::BCvt: + Val = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getValVT(), Val); + break; } + + ResultVals.push_back(Val); } // Merge everything together with a MERGE_VALUES node. From nicholas at mxc.ca Sat Apr 25 01:42:37 2009 From: nicholas at mxc.ca (Nick Lewycky) Date: Fri, 24 Apr 2009 23:42:37 -0700 Subject: [llvm-commits] [llvm] r69952 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/CellSPU/ lib/Target/PowerPC/ lib/Target/X86/ test/CodeGen/X86/ utils/TableGen/ In-Reply-To: References: Message-ID: <49F2B0DD.7000408@mxc.ca> Nate Begeman wrote: > Duncan / Rafael: > > What are you seeing for these tests that fail? I don't have a linux > machine to test on, and none of the automated builders complained. Yes they did. Here's one such example: http://google1.osuosl.org:8011/builders/clang-x86_64-linux/builds/1818/steps/test-llvm/logs/stdio The four failures your patch introduced being CodeGen/Generic/vector-casts.ll, CodeGen/X86/mmx-arith.ll, CodeGen/X86/vec_set.ll and CodeGen/X86/vec_shuffle-6.ll. Nick > Could you send the full output that doesn't match? > > Thanks, > Nate > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From sanjiv.gupta at microchip.com Sat Apr 25 02:25:32 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Sat, 25 Apr 2009 12:55:32 +0530 Subject: [llvm-commits] [llvm] r69971 - /llvm/trunk/docs/LangRef.html In-Reply-To: <200904241953.59660.baldrick@free.fr> References: <200904241638.n3OGcRFx006947@zion.cs.uiuc.edu> <200904241953.59660.baldrick@free.fr> Message-ID: <49F2BAEC.3030304@microchip.com> Duncan Sands wrote: > Hi Sanjiv, > > >> ; yields i16*:iptr >> > > Now yields i32*. > > Ah. Will fix that. >> - %iptr = getelementptr [10 x i16]* @arr, i16 0, i16 0 >> + %iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0 >> > > Ciao, > > Duncan. > From sanjiv.gupta at microchip.com Sat Apr 25 02:27:47 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Sat, 25 Apr 2009 07:27:47 -0000 Subject: [llvm-commits] [llvm] r70019 - /llvm/trunk/docs/LangRef.html Message-ID: <200904250727.n3P7RmAe003232@zion.cs.uiuc.edu> Author: sgupta Date: Sat Apr 25 02:27:44 2009 New Revision: 70019 URL: http://llvm.org/viewvc/llvm-project?rev=70019&view=rev Log: Fixed the gep example for i16 type indices. Modified: llvm/trunk/docs/LangRef.html Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=70019&r1=70018&r2=70019&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Sat Apr 25 02:27:44 2009 @@ -3718,7 +3718,7 @@ %vptr = getelementptr {i32, <2 x i8>}* %svptr, i64 0, i32 1, i32 1 ; yields i8*:eptr %eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1 - ; yields i16*:iptr + ; yields i32*:iptr %iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0 From evan.cheng at apple.com Sat Apr 25 04:25:20 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Sat, 25 Apr 2009 09:25:20 -0000 Subject: [llvm-commits] [llvm] r70026 - in /llvm/trunk: include/llvm/CodeGen/LiveInterval.h lib/CodeGen/LiveInterval.cpp test/CodeGen/X86/2009-04-25-CoalescerBug.ll Message-ID: <200904250925.n3P9PKUV017913@zion.cs.uiuc.edu> Author: evancheng Date: Sat Apr 25 04:25:19 2009 New Revision: 70026 URL: http://llvm.org/viewvc/llvm-project?rev=70026&view=rev Log: Do not share a single unknown val# for all the live ranges merged into a physical sub-register live interval. When coalescer is merging in clobbered virtaul register live interval into a physical register live interval, give each virtual register val# a separate val# in the physical register live interval. Otherwise, the coalescer would have lost track of the definitions information it needs to make correct coalescing decisions. Added: llvm/trunk/test/CodeGen/X86/2009-04-25-CoalescerBug.ll Modified: llvm/trunk/include/llvm/CodeGen/LiveInterval.h llvm/trunk/lib/CodeGen/LiveInterval.cpp Modified: llvm/trunk/include/llvm/CodeGen/LiveInterval.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LiveInterval.h?rev=70026&r1=70025&r2=70026&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/LiveInterval.h (original) +++ llvm/trunk/include/llvm/CodeGen/LiveInterval.h Sat Apr 25 04:25:19 2009 @@ -213,10 +213,6 @@ return VNI; } - /// getUnknownValNo - Find a value# for unknown values, if there isn't one - /// create a new one. - VNInfo *getUnknownValNo(BumpPtrAllocator &VNInfoAllocator); - /// addKill - Add a kill instruction index to the specified value /// number. static void addKill(VNInfo *VNI, unsigned KillIdx) { Modified: llvm/trunk/lib/CodeGen/LiveInterval.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveInterval.cpp?rev=70026&r1=70025&r2=70026&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveInterval.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveInterval.cpp Sat Apr 25 04:25:19 2009 @@ -19,6 +19,7 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/LiveInterval.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Streams.h" @@ -567,20 +568,6 @@ } } -VNInfo *LiveInterval::getUnknownValNo(BumpPtrAllocator &VNInfoAllocator) { - unsigned i = getNumValNums(); - if (i) { - do { - --i; - VNInfo *VNI = getValNumInfo(i); - if (VNI->def == ~0U && !VNI->copy && - !VNI->hasPHIKill && !VNI->redefByEC && VNI->kills.empty()) - return VNI; - } while (i != 0); - } - return getNextValue(~0U, 0, VNInfoAllocator); -} - /// MergeInClobberRanges - For any live ranges that are not defined in the /// current interval, but are defined in the Clobbers interval, mark them @@ -589,12 +576,19 @@ BumpPtrAllocator &VNInfoAllocator) { if (Clobbers.empty()) return; - // Find a value # to use for the clobber ranges. If there is already a value# - // for unknown values, use it. - VNInfo *ClobberValNo = getUnknownValNo(VNInfoAllocator); - + DenseMap ValNoMaps; iterator IP = begin(); for (const_iterator I = Clobbers.begin(), E = Clobbers.end(); I != E; ++I) { + // For every val# in the Clobbers interval, create a new "unknown" val#. + VNInfo *ClobberValNo = 0; + DenseMap::iterator VI = ValNoMaps.find(I->valno); + if (VI != ValNoMaps.end()) + ClobberValNo = VI->second; + else { + ClobberValNo = getNextValue(~0U, 0, VNInfoAllocator); + ValNoMaps.insert(std::make_pair(I->valno, ClobberValNo)); + } + bool Done = false; unsigned Start = I->start, End = I->end; // If a clobber range starts before an existing range and ends after @@ -637,7 +631,7 @@ BumpPtrAllocator &VNInfoAllocator) { // Find a value # to use for the clobber ranges. If there is already a value# // for unknown values, use it. - VNInfo *ClobberValNo = getUnknownValNo(VNInfoAllocator); + VNInfo *ClobberValNo = getNextValue(~0U, 0, VNInfoAllocator); iterator IP = begin(); IP = std::upper_bound(IP, end(), Start); Added: llvm/trunk/test/CodeGen/X86/2009-04-25-CoalescerBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-04-25-CoalescerBug.ll?rev=70026&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/2009-04-25-CoalescerBug.ll (added) +++ llvm/trunk/test/CodeGen/X86/2009-04-25-CoalescerBug.ll Sat Apr 25 04:25:19 2009 @@ -0,0 +1,19 @@ +; RUN: llvm-as < %s | llc -march=x86-64 | grep mov | count 2 +; rdar://6806252 + +define i64 @test(i32* %tmp13) nounwind { +entry: + br label %while.cond + +while.cond: ; preds = %while.cond, %entry + %tmp15 = load i32* %tmp13 ; [#uses=2] + %bf.lo = lshr i32 %tmp15, 1 ; [#uses=1] + %bf.lo.cleared = and i32 %bf.lo, 2147483647 ; [#uses=1] + %conv = zext i32 %bf.lo.cleared to i64 ; [#uses=1] + %bf.lo.cleared25 = and i32 %tmp15, 1 ; [#uses=1] + %tobool = icmp ne i32 %bf.lo.cleared25, 0 ; [#uses=1] + br i1 %tobool, label %while.cond, label %while.end + +while.end: ; preds = %while.cond + ret i64 %conv +} From isanbard at gmail.com Sat Apr 25 04:30:20 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 09:30:20 -0000 Subject: [llvm-commits] [llvm] r70029 - /llvm/tags/Apple/llvmCore-2107/ Message-ID: <200904250930.n3P9UKKj018096@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 04:30:18 2009 New Revision: 70029 URL: http://llvm.org/viewvc/llvm-project?rev=70029&view=rev Log: Creating llvmCore-2107 from Dib. Added: llvm/tags/Apple/llvmCore-2107/ - copied from r70028, llvm/branches/Apple/Dib/ From isanbard at gmail.com Sat Apr 25 04:30:49 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 09:30:49 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r70030 - /llvm-gcc-4.2/tags/Apple/llvmgcc42-2107/ Message-ID: <200904250930.n3P9UnVs018117@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 04:30:49 2009 New Revision: 70030 URL: http://llvm.org/viewvc/llvm-project?rev=70030&view=rev Log: Creating llvmgcc42-2107 from Dib. Added: llvm-gcc-4.2/tags/Apple/llvmgcc42-2107/ - copied from r70029, llvm-gcc-4.2/branches/Apple/Dib/ From isanbard at gmail.com Sat Apr 25 04:32:25 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 09:32:25 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r70031 - /llvm-gcc-4.2/tags/Apple/llvmgcc42-2107/ Message-ID: <200904250932.n3P9WPOh018174@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 04:32:24 2009 New Revision: 70031 URL: http://llvm.org/viewvc/llvm-project?rev=70031&view=rev Log: Retag to pick up a needed patch. Removed: llvm-gcc-4.2/tags/Apple/llvmgcc42-2107/ From isanbard at gmail.com Sat Apr 25 04:32:46 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 09:32:46 -0000 Subject: [llvm-commits] [llvm] r70032 - /llvm/tags/Apple/llvmCore-2107/ Message-ID: <200904250932.n3P9WkTL018192@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 04:32:46 2009 New Revision: 70032 URL: http://llvm.org/viewvc/llvm-project?rev=70032&view=rev Log: Retag to pick up a needed patch. Removed: llvm/tags/Apple/llvmCore-2107/ From isanbard at gmail.com Sat Apr 25 04:38:13 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 09:38:13 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r70033 - /llvm-gcc-4.2/tags/Apple/llvmgcc42-2107/ Message-ID: <200904250938.n3P9cDUb018399@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 04:38:13 2009 New Revision: 70033 URL: http://llvm.org/viewvc/llvm-project?rev=70033&view=rev Log: Creating llvmgcc42-2107 from Dib. Added: llvm-gcc-4.2/tags/Apple/llvmgcc42-2107/ - copied from r70032, llvm-gcc-4.2/branches/Apple/Dib/ From isanbard at gmail.com Sat Apr 25 04:38:31 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 09:38:31 -0000 Subject: [llvm-commits] [llvm] r70034 - /llvm/tags/Apple/llvmCore-2107/ Message-ID: <200904250938.n3P9cVwj018416@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 04:38:30 2009 New Revision: 70034 URL: http://llvm.org/viewvc/llvm-project?rev=70034&view=rev Log: Creating llvmCore-2107 from Dib. Added: llvm/tags/Apple/llvmCore-2107/ - copied from r70033, llvm/branches/Apple/Dib/ From natebegeman at me.com Sat Apr 25 04:49:34 2009 From: natebegeman at me.com (Nate Begeman) Date: Sat, 25 Apr 2009 02:49:34 -0700 Subject: [llvm-commits] [llvm] r69952 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/CellSPU/ lib/Target/PowerPC/ lib/Target/X86/ test/CodeGen/X86/ utils/TableGen/ In-Reply-To: <49F2B0DD.7000408@mxc.ca> References: <49F2B0DD.7000408@mxc.ca> Message-ID: <0EA9B983-1FF8-41E6-8F54-0600E13BB57B@me.com> On Apr 24, 2009, at 11:42 PM, Nick Lewycky wrote: > Nate Begeman wrote: >> Duncan / Rafael: >> >> What are you seeing for these tests that fail? I don't have a linux >> machine to test on, and none of the automated builders complained. > > Yes they did. Here's one such example: > > http://google1.osuosl.org:8011/builders/clang-x86_64-linux/builds/1818/steps/test-llvm/logs/stdio Thanks for the link Nick, the IRC connection must have been down or something, since nothing showed up in #llvm (the buildbots usually complain there). > The four failures your patch introduced being > CodeGen/Generic/vector-casts.ll, CodeGen/X86/mmx-arith.ll, > CodeGen/X86/vec_set.ll and CodeGen/X86/vec_shuffle-6.ll. I've reworked a bit of the patch based on duncan's feedback, but I can't get these tests to fail before or after my revisions using a linux target triple on my darwin machine. I'll see if i can track down a linux machine to test on. Nate From isanbard at gmail.com Sat Apr 25 04:54:59 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 09:54:59 -0000 Subject: [llvm-commits] [llvm] r70035 - /llvm/tags/Apple/llvmCore-2107/ Message-ID: <200904250954.n3P9sxKW018890@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 04:54:52 2009 New Revision: 70035 URL: http://llvm.org/viewvc/llvm-project?rev=70035&view=rev Log: Retag to pick up a needed patch. Removed: llvm/tags/Apple/llvmCore-2107/ From isanbard at gmail.com Sat Apr 25 05:00:19 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 10:00:19 -0000 Subject: [llvm-commits] [llvm] r70037 - /llvm/tags/Apple/llvmCore-2107/ Message-ID: <200904251000.n3PA0Kqu019141@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 05:00:18 2009 New Revision: 70037 URL: http://llvm.org/viewvc/llvm-project?rev=70037&view=rev Log: Creating llvmCore-2107 from Dib. Added: llvm/tags/Apple/llvmCore-2107/ - copied from r70036, llvm/branches/Apple/Dib/ From edwintorok at gmail.com Sat Apr 25 05:25:20 2009 From: edwintorok at gmail.com (Torok Edwin) Date: Sat, 25 Apr 2009 10:25:20 -0000 Subject: [llvm-commits] [llvm] r70038 - in /llvm/trunk: lib/System/Path.cpp test/Assembler/bcwrap.ll Message-ID: <200904251025.n3PAPLoS020026@zion.cs.uiuc.edu> Author: edwin Date: Sat Apr 25 05:25:12 2009 New Revision: 70038 URL: http://llvm.org/viewvc/llvm-project?rev=70038&view=rev Log: Fix g++-4.4.0 warning, it was causing llvm-nm to fail on wrapped BC files: Path.cpp:59: warning: case label value exceeds maximum value for type magic[0] is a (signed) char, but some case values are unsigned (e.g. 0xde). When magic[0] was 0xde, the switch has taken the default branch instead of case 0xde branch. Apparently this was the behaviour with older versions of gcc too, but not with g++. Now g++-4.4 behaves as gcc, and ignores unsigned case values out of range signed range. Added: llvm/trunk/test/Assembler/bcwrap.ll Modified: llvm/trunk/lib/System/Path.cpp Modified: llvm/trunk/lib/System/Path.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Path.cpp?rev=70038&r1=70037&r2=70038&view=diff ============================================================================== --- llvm/trunk/lib/System/Path.cpp (original) +++ llvm/trunk/lib/System/Path.cpp Sat Apr 25 05:25:12 2009 @@ -55,7 +55,7 @@ sys::IdentifyFileType(const char *magic, unsigned length) { assert(magic && "Invalid magic number string"); assert(length >=4 && "Invalid magic number length"); - switch (magic[0]) { + switch ((unsigned char)magic[0]) { case 0xDE: // 0x0B17C0DE = BC wraper if (magic[1] == (char)0xC0 && magic[2] == (char)0x17 && magic[3] == (char)0x0B) Added: llvm/trunk/test/Assembler/bcwrap.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/bcwrap.ll?rev=70038&view=auto ============================================================================== --- llvm/trunk/test/Assembler/bcwrap.ll (added) +++ llvm/trunk/test/Assembler/bcwrap.ll Sat Apr 25 05:25:12 2009 @@ -0,0 +1,9 @@ +; RUN: llvm-as < %s > %t +; RUN: llvm-nm %t | grep foo +; test for isBitcodeFile, llvm-nm must read from a file for this test +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" +target triple = "i686-apple-darwin9.2.2" + +define i32 @foo() { + ret i32 0 +} From isanbard at gmail.com Sat Apr 25 07:21:40 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 12:21:40 -0000 Subject: [llvm-commits] [llvm] r70042 - /llvm/tags/Apple/llvmCore-2107/ Message-ID: <200904251221.n3PCLe4M023287@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 07:21:39 2009 New Revision: 70042 URL: http://llvm.org/viewvc/llvm-project?rev=70042&view=rev Log: Retag to remove broken patch. Removed: llvm/tags/Apple/llvmCore-2107/ From isanbard at gmail.com Sat Apr 25 07:22:07 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 12:22:07 -0000 Subject: [llvm-commits] [llvm] r70043 - /llvm/tags/Apple/llvmCore-2107/ Message-ID: <200904251222.n3PCM7IA023314@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 07:22:07 2009 New Revision: 70043 URL: http://llvm.org/viewvc/llvm-project?rev=70043&view=rev Log: Creating llvmCore-2107 from Dib. Added: llvm/tags/Apple/llvmCore-2107/ - copied from r70042, llvm/branches/Apple/Dib/ From kremenek at apple.com Sat Apr 25 11:05:32 2009 From: kremenek at apple.com (Ted Kremenek) Date: Sat, 25 Apr 2009 16:05:32 -0000 Subject: [llvm-commits] [llvm] r70047 - /llvm/tags/checker/checker-0.189/ Message-ID: <200904251605.n3PG5W7T030318@zion.cs.uiuc.edu> Author: kremenek Date: Sat Apr 25 11:05:32 2009 New Revision: 70047 URL: http://llvm.org/viewvc/llvm-project?rev=70047&view=rev Log: Removing checker-0.189. Removed: llvm/tags/checker/checker-0.189/ From kremenek at apple.com Sat Apr 25 11:05:49 2009 From: kremenek at apple.com (Ted Kremenek) Date: Sat, 25 Apr 2009 16:05:49 -0000 Subject: [llvm-commits] [llvm] r70049 - /llvm/tags/checker/checker-0.189/ Message-ID: <200904251605.n3PG5nUH030349@zion.cs.uiuc.edu> Author: kremenek Date: Sat Apr 25 11:05:49 2009 New Revision: 70049 URL: http://llvm.org/viewvc/llvm-project?rev=70049&view=rev Log: Tagging checker-0.189. Added: llvm/tags/checker/checker-0.189/ - copied from r70048, llvm/trunk/ From gohman at apple.com Sat Apr 25 12:05:40 2009 From: gohman at apple.com (Dan Gohman) Date: Sat, 25 Apr 2009 17:05:40 -0000 Subject: [llvm-commits] [llvm] r70051 - in /llvm/trunk: lib/Analysis/ScalarEvolution.cpp test/Transforms/IndVarSimplify/avoid-i0.ll Message-ID: <200904251705.n3PH5ftk032057@zion.cs.uiuc.edu> Author: djg Date: Sat Apr 25 12:05:40 2009 New Revision: 70051 URL: http://llvm.org/viewvc/llvm-project?rev=70051&view=rev Log: Handle ands with 0 and shifts by 0 correctly. These aren't common, but indvars shouldn't crash on them. This fixes PR4054. Added: llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=70051&r1=70050&r2=70051&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Sat Apr 25 12:05:40 2009 @@ -1754,6 +1754,8 @@ // For an expression like x&255 that merely masks off the high bits, // use zext(trunc(x)) as the SCEV expression. if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + if (CI->isNullValue()) + return getSCEV(U->getOperand(1)); const APInt &A = CI->getValue(); unsigned Ones = A.countTrailingOnes(); if (APIntOps::isMask(Ones, A)) @@ -1818,10 +1820,15 @@ if (Instruction *L = dyn_cast(U->getOperand(0))) if (L->getOpcode() == Instruction::Shl && L->getOperand(1) == U->getOperand(1)) { - uint64_t Amt = getTypeSizeInBits(U->getType()) - CI->getZExtValue(); + unsigned BitWidth = getTypeSizeInBits(U->getType()); + uint64_t Amt = BitWidth - CI->getZExtValue(); + if (Amt == BitWidth) + return getSCEV(L->getOperand(0)); // shift by zero --> noop + if (Amt > BitWidth) + return getIntegerSCEV(0, U->getType()); // value is undefined return getSignExtendExpr(getTruncateExpr(getSCEV(L->getOperand(0)), - IntegerType::get(Amt)), + IntegerType::get(Amt)), U->getType()); } break; Added: llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll?rev=70051&view=auto ============================================================================== --- llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll (added) +++ llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll Sat Apr 25 12:05:40 2009 @@ -0,0 +1,23 @@ +; RUN: llvm-as < %s | opt -indvars +; PR4054 + +; Don't treat an and with 0 as a mask (trunc+zext). + +define i32 @int80(i8 signext %p_71) nounwind { +entry: + br label %bb + +bb: ; preds = %bb6, %entry + %p_71_addr.0 = phi i8 [ %p_71, %entry ], [ %0, %bb6 ] ; [#uses=0] + br i1 false, label %bb4, label %bb1 + +bb1: ; preds = %bb + ret i32 0 + +bb4: ; preds = %bb4, %bb + br i1 false, label %bb6, label %bb4 + +bb6: ; preds = %bb4 + %0 = and i8 0, 0 ; [#uses=1] + br label %bb +} From gohman at apple.com Sat Apr 25 12:09:45 2009 From: gohman at apple.com (Dan Gohman) Date: Sat, 25 Apr 2009 17:09:45 -0000 Subject: [llvm-commits] [llvm] r70052 - /llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200904251709.n3PH9k8k032202@zion.cs.uiuc.edu> Author: djg Date: Sat Apr 25 12:09:45 2009 New Revision: 70052 URL: http://llvm.org/viewvc/llvm-project?rev=70052&view=rev Log: Add a top-level comment about DAGCombiner's role in the compiler. 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=70052&r1=70051&r2=70052&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Sat Apr 25 12:09:45 2009 @@ -10,6 +10,10 @@ // This pass combines dag nodes to form fewer, simpler DAG nodes. It can be run // both before and after the DAG is legalized. // +// This pass is not a substitute for the LLVM IR instcombine pass. This pass is +// primarily intended to handle simplification opportunities that are implicit +// in the LLVM IR and exposed by the various codegen lowering phases. +// //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dagcombine" From gohman at apple.com Sat Apr 25 12:12:48 2009 From: gohman at apple.com (Dan Gohman) Date: Sat, 25 Apr 2009 17:12:48 -0000 Subject: [llvm-commits] [llvm] r70053 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/signed-comparison.ll Message-ID: <200904251712.n3PHCmrg032301@zion.cs.uiuc.edu> Author: djg Date: Sat Apr 25 12:12:48 2009 New Revision: 70053 URL: http://llvm.org/viewvc/llvm-project?rev=70053&view=rev Log: Add several more icmp simplifications. Transform signed comparisons into unsigned ones when the operands are known to have the same sign bit value. Added: llvm/trunk/test/Transforms/InstCombine/signed-comparison.ll Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=70053&r1=70052&r2=70053&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sat Apr 25 12:12:48 2009 @@ -708,15 +708,13 @@ // set of known zero and one bits, compute the maximum and minimum values that // could have the specified known zero and known one bits, returning them in // min/max. -static void ComputeSignedMinMaxValuesFromKnownBits(const Type *Ty, - const APInt& KnownZero, +static void ComputeSignedMinMaxValuesFromKnownBits(const APInt& KnownZero, const APInt& KnownOne, APInt& Min, APInt& Max) { - uint32_t BitWidth = cast(Ty)->getBitWidth(); - assert(KnownZero.getBitWidth() == BitWidth && - KnownOne.getBitWidth() == BitWidth && - Min.getBitWidth() == BitWidth && Max.getBitWidth() == BitWidth && - "Ty, KnownZero, KnownOne and Min, Max must have equal bitwidth."); + assert(KnownZero.getBitWidth() == KnownOne.getBitWidth() && + KnownZero.getBitWidth() == Min.getBitWidth() && + KnownZero.getBitWidth() == Max.getBitWidth() && + "KnownZero, KnownOne and Min, Max must have equal bitwidth."); APInt UnknownBits = ~(KnownZero|KnownOne); // The minimum value is when all unknown bits are zeros, EXCEPT for the sign @@ -724,9 +722,9 @@ Min = KnownOne; Max = KnownOne|UnknownBits; - if (UnknownBits[BitWidth-1]) { // Sign bit is unknown - Min.set(BitWidth-1); - Max.clear(BitWidth-1); + if (UnknownBits.isNegative()) { // Sign bit is unknown + Min.set(Min.getBitWidth()-1); + Max.clear(Max.getBitWidth()-1); } } @@ -734,14 +732,12 @@ // a set of known zero and one bits, compute the maximum and minimum values that // could have the specified known zero and known one bits, returning them in // min/max. -static void ComputeUnsignedMinMaxValuesFromKnownBits(const Type *Ty, - const APInt &KnownZero, +static void ComputeUnsignedMinMaxValuesFromKnownBits(const APInt &KnownZero, const APInt &KnownOne, APInt &Min, APInt &Max) { - uint32_t BitWidth = cast(Ty)->getBitWidth(); BitWidth = BitWidth; - assert(KnownZero.getBitWidth() == BitWidth && - KnownOne.getBitWidth() == BitWidth && - Min.getBitWidth() == BitWidth && Max.getBitWidth() && + assert(KnownZero.getBitWidth() == KnownOne.getBitWidth() && + KnownZero.getBitWidth() == Min.getBitWidth() && + KnownZero.getBitWidth() == Max.getBitWidth() && "Ty, KnownZero, KnownOne and Min, Max must have equal bitwidth."); APInt UnknownBits = ~(KnownZero|KnownOne); @@ -808,9 +804,13 @@ assert(V != 0 && "Null pointer of Value???"); assert(Depth <= 6 && "Limit Search Depth"); uint32_t BitWidth = DemandedMask.getBitWidth(); - const IntegerType *VTy = cast(V->getType()); - assert(VTy->getBitWidth() == BitWidth && - KnownZero.getBitWidth() == BitWidth && + const Type *VTy = V->getType(); + assert((TD || !isa(VTy)) && + "SimplifyDemandedBits needs to know bit widths!"); + assert((!TD || TD->getTypeSizeInBits(VTy) == BitWidth) && + (!isa(VTy) || + VTy->getPrimitiveSizeInBits() == BitWidth) && + KnownZero.getBitWidth() == BitWidth && KnownOne.getBitWidth() == BitWidth && "Value *V, DemandedMask, KnownZero and KnownOne \ must have same BitWidth"); @@ -820,7 +820,13 @@ KnownZero = ~KnownOne & DemandedMask; return 0; } - + if (isa(V)) { + // We know all of the bits for a constant! + KnownOne.clear(); + KnownZero = DemandedMask; + return 0; + } + KnownZero.clear(); KnownOne.clear(); if (DemandedMask == 0) { // Not demanding any bits from V. @@ -832,12 +838,15 @@ if (Depth == 6) // Limit search depth. return 0; - Instruction *I = dyn_cast(V); - if (!I) return 0; // Only analyze instructions. - APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0); APInt &RHSKnownZero = KnownZero, &RHSKnownOne = KnownOne; + Instruction *I = dyn_cast(V); + if (!I) { + ComputeMaskedBits(V, DemandedMask, RHSKnownZero, RHSKnownOne, Depth); + return 0; // Only analyze instructions. + } + // If there are multiple uses of this value and we aren't at the root, then // we can't do any simplifications of the operands, because DemandedMask // only reflects the bits demanded by *one* of the users. @@ -1399,8 +1408,12 @@ // If the client is only demanding bits that we know, return the known // constant. - if ((DemandedMask & (RHSKnownZero|RHSKnownOne)) == DemandedMask) - return ConstantInt::get(RHSKnownOne); + if ((DemandedMask & (RHSKnownZero|RHSKnownOne)) == DemandedMask) { + Constant *C = ConstantInt::get(RHSKnownOne); + if (isa(V->getType())) + C = ConstantExpr::getIntToPtr(C, V->getType()); + return C; + } return false; } @@ -5831,6 +5844,14 @@ } } + unsigned BitWidth = 0; + if (TD) + BitWidth = TD->getTypeSizeInBits(Ty); + else if (isa(Ty)) + BitWidth = Ty->getPrimitiveSizeInBits(); + + bool isSignBit = false; + // See if we are doing a comparison with a constant. if (ConstantInt *CI = dyn_cast(Op1)) { Value *A = 0, *B = 0; @@ -5865,105 +5886,161 @@ return new ICmpInst(ICmpInst::ICMP_SGT, Op0, SubOne(CI)); } - // See if we can fold the comparison based on range information we can get - // by checking whether bits are known to be zero or one in the input. - uint32_t BitWidth = cast(Ty)->getBitWidth(); - APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); - // If this comparison is a normal comparison, it demands all // bits, if it is a sign bit comparison, it only demands the sign bit. bool UnusedBit; - bool isSignBit = isSignBitCheck(I.getPredicate(), CI, UnusedBit); - - if (SimplifyDemandedBits(I.getOperandUse(0), + isSignBit = isSignBitCheck(I.getPredicate(), CI, UnusedBit); + } + + // See if we can fold the comparison based on range information we can get + // by checking whether bits are known to be zero or one in the input. + if (BitWidth != 0) { + APInt Op0KnownZero(BitWidth, 0), Op0KnownOne(BitWidth, 0); + APInt Op1KnownZero(BitWidth, 0), Op1KnownOne(BitWidth, 0); + + if (SimplifyDemandedBits(I.getOperandUse(0), isSignBit ? APInt::getSignBit(BitWidth) : APInt::getAllOnesValue(BitWidth), - KnownZero, KnownOne, 0)) + Op0KnownZero, Op0KnownOne, 0)) return &I; - + if (SimplifyDemandedBits(I.getOperandUse(1), + APInt::getAllOnesValue(BitWidth), + Op1KnownZero, Op1KnownOne, 0)) + return &I; + // Given the known and unknown bits, compute a range that the LHS could be // in. Compute the Min, Max and RHS values based on the known bits. For the // EQ and NE we use unsigned values. - APInt Min(BitWidth, 0), Max(BitWidth, 0); - if (ICmpInst::isSignedPredicate(I.getPredicate())) - ComputeSignedMinMaxValuesFromKnownBits(Ty, KnownZero, KnownOne, Min, Max); - else - ComputeUnsignedMinMaxValuesFromKnownBits(Ty, KnownZero, KnownOne,Min,Max); - + APInt Op0Min(BitWidth, 0), Op0Max(BitWidth, 0); + APInt Op1Min(BitWidth, 0), Op1Max(BitWidth, 0); + if (ICmpInst::isSignedPredicate(I.getPredicate())) { + ComputeSignedMinMaxValuesFromKnownBits(Op0KnownZero, Op0KnownOne, + Op0Min, Op0Max); + ComputeSignedMinMaxValuesFromKnownBits(Op1KnownZero, Op1KnownOne, + Op1Min, Op1Max); + } else { + ComputeUnsignedMinMaxValuesFromKnownBits(Op0KnownZero, Op0KnownOne, + Op0Min, Op0Max); + ComputeUnsignedMinMaxValuesFromKnownBits(Op1KnownZero, Op1KnownOne, + Op1Min, Op1Max); + } + // If Min and Max are known to be the same, then SimplifyDemandedBits // figured out that the LHS is a constant. Just constant fold this now so // that code below can assume that Min != Max. - if (Min == Max) - return ReplaceInstUsesWith(I, ConstantExpr::getICmp(I.getPredicate(), - ConstantInt::get(Min), - CI)); - + if (!isa(Op0) && Op0Min == Op0Max) + return new ICmpInst(I.getPredicate(), ConstantInt::get(Op0Min), Op1); + if (!isa(Op1) && Op1Min == Op1Max) + return new ICmpInst(I.getPredicate(), Op0, ConstantInt::get(Op1Min)); + // Based on the range information we know about the LHS, see if we can // simplify this comparison. For example, (x&4) < 8 is always true. - const APInt &RHSVal = CI->getValue(); - switch (I.getPredicate()) { // LE/GE have been folded already. + switch (I.getPredicate()) { default: assert(0 && "Unknown icmp opcode!"); case ICmpInst::ICMP_EQ: - if (Max.ult(RHSVal) || Min.ugt(RHSVal)) + if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getFalse()); break; case ICmpInst::ICMP_NE: - if (Max.ult(RHSVal) || Min.ugt(RHSVal)) + if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getTrue()); break; case ICmpInst::ICMP_ULT: - if (Max.ult(RHSVal)) // A true iff max(A) < C + if (Op0Max.ult(Op1Min)) // A true if max(A) < min(B) return ReplaceInstUsesWith(I, ConstantInt::getTrue()); - if (Min.uge(RHSVal)) // A false iff min(A) >= C + if (Op0Min.uge(Op1Max)) // A false if min(A) >= max(B) return ReplaceInstUsesWith(I, ConstantInt::getFalse()); - if (RHSVal == Max) // A A != MAX + if (Op1Min == Op0Max) // A A != B if max(A) == min(B) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); - if (RHSVal == Min+1) // A A == MIN - return new ICmpInst(ICmpInst::ICMP_EQ, Op0, SubOne(CI)); - - // (x (x >s -1) -> true if sign bit clear - if (CI->isMinValue(true)) - return new ICmpInst(ICmpInst::ICMP_SGT, Op0, + if (ConstantInt *CI = dyn_cast(Op1)) { + if (Op1Max == Op0Min+1) // A A == C-1 if min(A)+1 == C + return new ICmpInst(ICmpInst::ICMP_EQ, Op0, SubOne(CI)); + + // (x (x >s -1) -> true if sign bit clear + if (CI->isMinValue(true)) + return new ICmpInst(ICmpInst::ICMP_SGT, Op0, ConstantInt::getAllOnesValue(Op0->getType())); + } break; case ICmpInst::ICMP_UGT: - if (Min.ugt(RHSVal)) // A >u C -> true iff min(A) > C + if (Op0Min.ugt(Op1Max)) // A >u B -> true if min(A) > max(B) return ReplaceInstUsesWith(I, ConstantInt::getTrue()); - if (Max.ule(RHSVal)) // A >u C -> false iff max(A) <= C + if (Op0Max.ule(Op1Min)) // A >u B -> false if max(A) <= max(B) return ReplaceInstUsesWith(I, ConstantInt::getFalse()); - - if (RHSVal == Min) // A >u MIN -> A != MIN + + if (Op1Max == Op0Min) // A >u B -> A != B if min(A) == max(B) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); - if (RHSVal == Max-1) // A >u MAX-1 -> A == MAX - return new ICmpInst(ICmpInst::ICMP_EQ, Op0, AddOne(CI)); - - // (x >u 2147483647) -> (x true if sign bit set - if (CI->isMaxValue(true)) - return new ICmpInst(ICmpInst::ICMP_SLT, Op0, - ConstantInt::getNullValue(Op0->getType())); + if (ConstantInt *CI = dyn_cast(Op1)) { + if (Op1Min == Op0Max-1) // A >u C -> A == C+1 if max(a)-1 == C + return new ICmpInst(ICmpInst::ICMP_EQ, Op0, AddOne(CI)); + + // (x >u 2147483647) -> (x true if sign bit set + if (CI->isMaxValue(true)) + return new ICmpInst(ICmpInst::ICMP_SLT, Op0, + ConstantInt::getNullValue(Op0->getType())); + } break; case ICmpInst::ICMP_SLT: - if (Max.slt(RHSVal)) // A true iff max(A) < C + if (Op0Max.slt(Op1Min)) // A true if max(A) < min(C) return ReplaceInstUsesWith(I, ConstantInt::getTrue()); - if (Min.sge(RHSVal)) // A false iff min(A) >= C + if (Op0Min.sge(Op1Max)) // A false if min(A) >= max(C) return ReplaceInstUsesWith(I, ConstantInt::getFalse()); - if (RHSVal == Max) // A A != MAX + if (Op1Min == Op0Max) // A A != B if max(A) == min(B) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); - if (RHSVal == Min+1) // A A == MIN - return new ICmpInst(ICmpInst::ICMP_EQ, Op0, SubOne(CI)); + if (ConstantInt *CI = dyn_cast(Op1)) { + if (Op1Max == Op0Min+1) // A A == C-1 if min(A)+1 == C + return new ICmpInst(ICmpInst::ICMP_EQ, Op0, SubOne(CI)); + } break; - case ICmpInst::ICMP_SGT: - if (Min.sgt(RHSVal)) // A >s C -> true iff min(A) > C + case ICmpInst::ICMP_SGT: + if (Op0Min.sgt(Op1Max)) // A >s B -> true if min(A) > max(B) return ReplaceInstUsesWith(I, ConstantInt::getTrue()); - if (Max.sle(RHSVal)) // A >s C -> false iff max(A) <= C + if (Op0Max.sle(Op1Min)) // A >s B -> false if max(A) <= min(B) return ReplaceInstUsesWith(I, ConstantInt::getFalse()); - - if (RHSVal == Min) // A >s MIN -> A != MIN + + if (Op1Max == Op0Min) // A >s B -> A != B if min(A) == max(B) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); - if (RHSVal == Max-1) // A >s MAX-1 -> A == MAX - return new ICmpInst(ICmpInst::ICMP_EQ, Op0, AddOne(CI)); + if (ConstantInt *CI = dyn_cast(Op1)) { + if (Op1Min == Op0Max-1) // A >s C -> A == C+1 if max(A)-1 == C + return new ICmpInst(ICmpInst::ICMP_EQ, Op0, AddOne(CI)); + } + break; + case ICmpInst::ICMP_SGE: + assert(!isa(Op1) && "ICMP_SGE with ConstantInt not folded!"); + if (Op0Min.sge(Op1Max)) // A >=s B -> true if min(A) >= max(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue()); + if (Op0Max.slt(Op1Min)) // A >=s B -> false if max(A) < min(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse()); + break; + case ICmpInst::ICMP_SLE: + assert(!isa(Op1) && "ICMP_SLE with ConstantInt not folded!"); + if (Op0Max.sle(Op1Min)) // A <=s B -> true if max(A) <= min(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue()); + if (Op0Min.sgt(Op1Max)) // A <=s B -> false if min(A) > max(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse()); + break; + case ICmpInst::ICMP_UGE: + assert(!isa(Op1) && "ICMP_UGE with ConstantInt not folded!"); + if (Op0Min.uge(Op1Max)) // A >=u B -> true if min(A) >= max(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue()); + if (Op0Max.ult(Op1Min)) // A >=u B -> false if max(A) < min(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse()); + break; + case ICmpInst::ICMP_ULE: + assert(!isa(Op1) && "ICMP_ULE with ConstantInt not folded!"); + if (Op0Max.ule(Op1Min)) // A <=u B -> true if max(A) <= min(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue()); + if (Op0Min.ugt(Op1Max)) // A <=u B -> false if min(A) > max(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse()); break; } + + // Turn a signed comparison into an unsigned one if both operands + // are known to have the same sign. + if (I.isSignedPredicate() && + ((Op0KnownZero.isNegative() && Op1KnownZero.isNegative()) || + (Op0KnownOne.isNegative() && Op1KnownOne.isNegative()))) + return new ICmpInst(I.getUnsignedPredicate(), Op0, Op1); } // Test if the ICmpInst instruction is used exclusively by a select as Added: llvm/trunk/test/Transforms/InstCombine/signed-comparison.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/signed-comparison.ll?rev=70053&view=auto ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/signed-comparison.ll (added) +++ llvm/trunk/test/Transforms/InstCombine/signed-comparison.ll Sat Apr 25 12:12:48 2009 @@ -0,0 +1,28 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis > %t +; RUN: not grep zext %t +; RUN: not grep slt %t +; RUN: grep {icmp ult} %t + +; Instcombine should convert the zext+slt into a simple ult. + +define void @foo(double* %p) nounwind { +entry: + br label %bb + +bb: + %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %bb ] + %t0 = and i64 %indvar, 65535 + %t1 = getelementptr double* %p, i64 %t0 + %t2 = load double* %t1, align 8 + %t3 = mul double %t2, 2.2 + store double %t3, double* %t1, align 8 + %i.04 = trunc i64 %indvar to i16 + %t4 = add i16 %i.04, 1 + %t5 = zext i16 %t4 to i32 + %t6 = icmp slt i32 %t5, 500 + %indvar.next = add i64 %indvar, 1 + br i1 %t6, label %bb, label %return + +return: + ret void +} From gohman at apple.com Sat Apr 25 12:28:46 2009 From: gohman at apple.com (Dan Gohman) Date: Sat, 25 Apr 2009 17:28:46 -0000 Subject: [llvm-commits] [llvm] r70054 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200904251728.n3PHSk4c000336@zion.cs.uiuc.edu> Author: djg Date: Sat Apr 25 12:28:45 2009 New Revision: 70054 URL: http://llvm.org/viewvc/llvm-project?rev=70054&view=rev Log: Return null instead of false, as appropriate. Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=70054&r1=70053&r2=70054&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sat Apr 25 12:28:45 2009 @@ -1485,7 +1485,7 @@ // Limit search depth. if (Depth == 10) - return false; + return 0; // If multiple users are using the root value, procede with // simplification conservatively assuming that all elements @@ -1496,14 +1496,14 @@ // the main instcombine process. if (Depth != 0) // TODO: Just compute the UndefElts information recursively. - return false; + return 0; // Conservatively assume that all elements are needed. DemandedElts = EltMask; } Instruction *I = dyn_cast(V); - if (!I) return false; // Only analyze instructions. + if (!I) return 0; // Only analyze instructions. bool MadeChange = false; APInt UndefElts2(VWidth, 0); From gohman at apple.com Sat Apr 25 12:55:53 2009 From: gohman at apple.com (Dan Gohman) Date: Sat, 25 Apr 2009 17:55:53 -0000 Subject: [llvm-commits] [llvm] r70056 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeFloatTypes.cpp LegalizeTypes.cpp LegalizeTypes.h LegalizeTypesGeneric.cpp Message-ID: <200904251755.n3PHtrvU001165@zion.cs.uiuc.edu> Author: djg Date: Sat Apr 25 12:55:53 2009 New Revision: 70056 URL: http://llvm.org/viewvc/llvm-project?rev=70056&view=rev Log: Refactor the code to grab the low and high parts of a value using EXTRACT_ELEMENT into a utility function. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp?rev=70056&r1=70055&r2=70056&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp Sat Apr 25 12:55:53 2009 @@ -860,12 +860,7 @@ RTLIB::ADD_F32, RTLIB::ADD_F64, RTLIB::ADD_F80, RTLIB::ADD_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FCEIL(SDNode *N, @@ -874,12 +869,7 @@ RTLIB::CEIL_F32, RTLIB::CEIL_F64, RTLIB::CEIL_F80, RTLIB::CEIL_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FCOS(SDNode *N, @@ -888,12 +878,7 @@ RTLIB::COS_F32, RTLIB::COS_F64, RTLIB::COS_F80, RTLIB::COS_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDValue &Lo, @@ -906,12 +891,7 @@ RTLIB::DIV_PPCF128), N->getValueType(0), Ops, 2, false, N->getDebugLoc()); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FEXP(SDNode *N, @@ -920,12 +900,7 @@ RTLIB::EXP_F32, RTLIB::EXP_F64, RTLIB::EXP_F80, RTLIB::EXP_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FEXP2(SDNode *N, @@ -934,12 +909,7 @@ RTLIB::EXP2_F32, RTLIB::EXP2_F64, RTLIB::EXP2_F80, RTLIB::EXP2_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N, @@ -948,12 +918,7 @@ RTLIB::FLOOR_F32,RTLIB::FLOOR_F64, RTLIB::FLOOR_F80,RTLIB::FLOOR_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FLOG(SDNode *N, @@ -962,12 +927,7 @@ RTLIB::LOG_F32, RTLIB::LOG_F64, RTLIB::LOG_F80, RTLIB::LOG_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FLOG2(SDNode *N, @@ -976,12 +936,7 @@ RTLIB::LOG2_F32, RTLIB::LOG2_F64, RTLIB::LOG2_F80, RTLIB::LOG2_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FLOG10(SDNode *N, @@ -990,12 +945,7 @@ RTLIB::LOG10_F32,RTLIB::LOG10_F64, RTLIB::LOG10_F80,RTLIB::LOG10_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDValue &Lo, @@ -1008,12 +958,7 @@ RTLIB::MUL_PPCF128), N->getValueType(0), Ops, 2, false, N->getDebugLoc()); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FNEARBYINT(SDNode *N, @@ -1024,12 +969,7 @@ RTLIB::NEARBYINT_F80, RTLIB::NEARBYINT_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo, @@ -1053,12 +993,7 @@ RTLIB::POW_F32, RTLIB::POW_F64, RTLIB::POW_F80, RTLIB::POW_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FPOWI(SDNode *N, @@ -1067,12 +1002,7 @@ RTLIB::POWI_F32, RTLIB::POWI_F64, RTLIB::POWI_F80, RTLIB::POWI_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FRINT(SDNode *N, @@ -1081,12 +1011,7 @@ RTLIB::RINT_F32, RTLIB::RINT_F64, RTLIB::RINT_F80, RTLIB::RINT_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FSIN(SDNode *N, @@ -1095,12 +1020,7 @@ RTLIB::SIN_F32, RTLIB::SIN_F64, RTLIB::SIN_F80, RTLIB::SIN_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FSQRT(SDNode *N, @@ -1109,12 +1029,7 @@ RTLIB::SQRT_F32, RTLIB::SQRT_F64, RTLIB::SQRT_F80, RTLIB::SQRT_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDValue &Lo, @@ -1127,12 +1042,7 @@ RTLIB::SUB_PPCF128), N->getValueType(0), Ops, 2, false, N->getDebugLoc()); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FTRUNC(SDNode *N, @@ -1141,12 +1051,7 @@ RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, RTLIB::TRUNC_F80, RTLIB::TRUNC_PPCF128), N, false); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - DebugLoc dl = N->getDebugLoc(); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Call, - DAG.getIntPtrConstant(1)); + GetPairElements(Call, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo, @@ -1214,10 +1119,7 @@ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!"); Hi = MakeLibCall(LC, VT, &Src, 1, true, dl); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Hi, - DAG.getIntPtrConstant(0)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Hi, - DAG.getIntPtrConstant(1)); + GetPairElements(Hi, Lo, Hi); } if (isSigned) @@ -1252,8 +1154,7 @@ MVT::ppcf128)); Lo = DAG.getNode(ISD::SELECT_CC, dl, VT, Src, DAG.getConstant(0, SrcVT), Lo, Hi, DAG.getCondCode(ISD::SETLT)); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Lo, DAG.getIntPtrConstant(1)); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Lo, DAG.getIntPtrConstant(0)); + GetPairElements(Lo, Lo, Hi); } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp?rev=70056&r1=70055&r2=70056&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp Sat Apr 25 12:55:53 2009 @@ -933,6 +933,18 @@ } } +/// GetPairElements - Use ISD::EXTRACT_ELEMENT nodes to extract the low and +/// high parts of the given value. +void DAGTypeLegalizer::GetPairElements(SDValue Pair, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = Pair.getDebugLoc(); + MVT NVT = TLI.getTypeToTransformTo(Pair.getValueType()); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Pair, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Pair, + DAG.getIntPtrConstant(1)); +} + SDValue DAGTypeLegalizer::GetVectorElementPointer(SDValue VecPtr, MVT EltVT, SDValue Index) { DebugLoc dl = Index.getDebugLoc(); Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=70056&r1=70055&r2=70056&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Sat Apr 25 12:55:53 2009 @@ -695,6 +695,10 @@ /// which is split (or expanded) into two not necessarily identical pieces. void GetSplitDestVTs(MVT InVT, MVT &LoVT, MVT &HiVT); + /// GetPairElements - Use ISD::EXTRACT_ELEMENT nodes to extract the low and + /// high parts of the given value. + void GetPairElements(SDValue Pair, SDValue &Lo, SDValue &Hi); + // Generic Result Splitting. void SplitRes_MERGE_VALUES(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitRes_SELECT (SDNode *N, SDValue &Lo, SDValue &Hi); Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp?rev=70056&r1=70055&r2=70056&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp Sat Apr 25 12:55:53 2009 @@ -135,16 +135,11 @@ GetExpandedOp(N->getOperand(0), Lo, Hi); SDValue Part = cast(N->getOperand(1))->getZExtValue() ? Hi : Lo; - DebugLoc dl = N->getDebugLoc(); assert(Part.getValueType() == N->getValueType(0) && "Type twice as big as expanded type not itself expanded!"); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Part, - DAG.getConstant(0, TLI.getPointerTy())); - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Part, - DAG.getConstant(1, TLI.getPointerTy())); + GetPairElements(Part, Lo, Hi); } void DAGTypeLegalizer::ExpandRes_EXTRACT_VECTOR_ELT(SDNode *N, SDValue &Lo, From sabre at nondot.org Sat Apr 25 13:27:23 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 18:27:23 -0000 Subject: [llvm-commits] [llvm] r70057 - /llvm/trunk/lib/Target/X86/X86Subtarget.cpp Message-ID: <200904251827.n3PIRNC4002254@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 13:27:23 2009 New Revision: 70057 URL: http://llvm.org/viewvc/llvm-project?rev=70057&view=rev Log: add support for detecting process features on win64, patch by Nicolas Capens! Modified: llvm/trunk/lib/Target/X86/X86Subtarget.cpp Modified: llvm/trunk/lib/Target/X86/X86Subtarget.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.cpp?rev=70057&r1=70056&r2=70057&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86Subtarget.cpp (original) +++ llvm/trunk/lib/Target/X86/X86Subtarget.cpp Sat Apr 25 13:27:23 2009 @@ -21,6 +21,10 @@ #include "llvm/Target/TargetOptions.h" using namespace llvm; +#if defined(_MSC_VER) + #include +#endif + static cl::opt AsmWriterFlavor("x86-asm-syntax", cl::init(X86Subtarget::Unset), cl::desc("Choose style of code to emit from X86 backend:"), @@ -110,43 +114,53 @@ /// specified arguments. If we can't run cpuid on the host, return true. bool X86::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { -#if defined(__x86_64__) - // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. - asm ("movq\t%%rbx, %%rsi\n\t" - "cpuid\n\t" - "xchgq\t%%rbx, %%rsi\n\t" - : "=a" (*rEAX), - "=S" (*rEBX), - "=c" (*rECX), - "=d" (*rEDX) - : "a" (value)); - return false; +#if defined(__x86_64__) || defined(_M_AMD64) + #if defined(__GNUC__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. + asm ("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + int registers[4]; + __cpuid(registers, value); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; + return false; + #endif #elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) -#if defined(__GNUC__) - asm ("movl\t%%ebx, %%esi\n\t" - "cpuid\n\t" - "xchgl\t%%ebx, %%esi\n\t" - : "=a" (*rEAX), - "=S" (*rEBX), - "=c" (*rECX), - "=d" (*rEDX) - : "a" (value)); - return false; -#elif defined(_MSC_VER) - __asm { - mov eax,value - cpuid - mov esi,rEAX - mov dword ptr [esi],eax - mov esi,rEBX - mov dword ptr [esi],ebx - mov esi,rECX - mov dword ptr [esi],ecx - mov esi,rEDX - mov dword ptr [esi],edx - } - return false; -#endif + #if defined(__GNUC__) + asm ("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + __asm { + mov eax,value + cpuid + mov esi,rEAX + mov dword ptr [esi],eax + mov esi,rEBX + mov dword ptr [esi],ebx + mov esi,rECX + mov dword ptr [esi],ecx + mov esi,rEDX + mov dword ptr [esi],edx + } + return false; + #endif #endif return true; } From sabre at nondot.org Sat Apr 25 13:34:04 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 18:34:04 -0000 Subject: [llvm-commits] [llvm] r70058 - in /llvm/trunk: lib/Support/APInt.cpp unittests/ADT/APIntTest.cpp Message-ID: <200904251834.n3PIY46A002449@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 13:34:04 2009 New Revision: 70058 URL: http://llvm.org/viewvc/llvm-project?rev=70058&view=rev Log: Fix PR4040: APInt's string constructor is too strict patch by Jeff Yasskin! Modified: llvm/trunk/lib/Support/APInt.cpp llvm/trunk/unittests/ADT/APIntTest.cpp Modified: llvm/trunk/lib/Support/APInt.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=70058&r1=70057&r2=70058&view=diff ============================================================================== --- llvm/trunk/lib/Support/APInt.cpp (original) +++ llvm/trunk/lib/Support/APInt.cpp Sat Apr 25 13:34:04 2009 @@ -1918,9 +1918,9 @@ if (isNeg) str++, slen--; assert((slen <= numbits || radix != 2) && "Insufficient bit width"); - assert((slen*3 <= numbits || radix != 8) && "Insufficient bit width"); - assert((slen*4 <= numbits || radix != 16) && "Insufficient bit width"); - assert(((slen*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); + assert(((slen-1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen-1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen-1)*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); // Allocate memory if (!isSingleWord()) @@ -1961,10 +1961,12 @@ } // Shift or multiply the value by the radix - if (shift) - *this <<= shift; - else - *this *= apradix; + if (slen > 1) { + if (shift) + *this <<= shift; + else + *this *= apradix; + } // Add in the digit we just interpreted if (apdigit.isSingleWord()) Modified: llvm/trunk/unittests/ADT/APIntTest.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APIntTest.cpp?rev=70058&r1=70057&r2=70058&view=diff ============================================================================== --- llvm/trunk/unittests/ADT/APIntTest.cpp (original) +++ llvm/trunk/unittests/ADT/APIntTest.cpp Sat Apr 25 13:34:04 2009 @@ -176,4 +176,13 @@ EXPECT_EQ(zero, one.srem(neg_one)); } +TEST(APIntTest, fromString) { + EXPECT_EQ(APInt(1, 0), APInt(1, "0", 1, 10)); + EXPECT_EQ(APInt(1, 1), APInt(1, "1", 1, 10)); + EXPECT_EQ(APInt(1, 1), APInt(1, "-1", 2, 10)); + EXPECT_EQ(APInt(1, 1), APInt(1, "1", 1, 2)); + EXPECT_EQ(APInt(1, 1), APInt(1, "1", 1, 8)); + EXPECT_EQ(APInt(1, 1), APInt(1, "1", 1, 16)); +} + } From sabre at nondot.org Sat Apr 25 14:50:29 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 19:50:29 -0000 Subject: [llvm-commits] [llvm] r70068 - /llvm/trunk/include/llvm/ADT/DenseMap.h Message-ID: <200904251950.n3PJoU7L005935@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 14:50:14 2009 New Revision: 70068 URL: http://llvm.org/viewvc/llvm-project?rev=70068&view=rev Log: DenseMap.h needs because it explicitly calls operator new/delete. Patch by John McCall! Modified: llvm/trunk/include/llvm/ADT/DenseMap.h Modified: llvm/trunk/include/llvm/ADT/DenseMap.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/DenseMap.h?rev=70068&r1=70067&r2=70068&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/DenseMap.h (original) +++ llvm/trunk/include/llvm/ADT/DenseMap.h Sat Apr 25 14:50:14 2009 @@ -18,6 +18,7 @@ #include "llvm/Support/MathExtras.h" #include #include +#include namespace llvm { From evan.cheng at apple.com Sat Apr 25 15:20:16 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Sat, 25 Apr 2009 20:20:16 -0000 Subject: [llvm-commits] [llvm] r70069 - /llvm/trunk/lib/CodeGen/LiveInterval.cpp Message-ID: <200904252020.n3PKKG8i006967@zion.cs.uiuc.edu> Author: evancheng Date: Sat Apr 25 15:20:15 2009 New Revision: 70069 URL: http://llvm.org/viewvc/llvm-project?rev=70069&view=rev Log: Reuse unused val#'s to avoid running out of memory in extreme cases. Modified: llvm/trunk/lib/CodeGen/LiveInterval.cpp Modified: llvm/trunk/lib/CodeGen/LiveInterval.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveInterval.cpp?rev=70069&r1=70068&r2=70069&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveInterval.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveInterval.cpp Sat Apr 25 15:20:15 2009 @@ -577,6 +577,7 @@ if (Clobbers.empty()) return; DenseMap ValNoMaps; + VNInfo *UnusedValNo = 0; iterator IP = begin(); for (const_iterator I = Clobbers.begin(), E = Clobbers.end(); I != E; ++I) { // For every val# in the Clobbers interval, create a new "unknown" val#. @@ -584,8 +585,10 @@ DenseMap::iterator VI = ValNoMaps.find(I->valno); if (VI != ValNoMaps.end()) ClobberValNo = VI->second; + else if (UnusedValNo) + ClobberValNo = UnusedValNo; else { - ClobberValNo = getNextValue(~0U, 0, VNInfoAllocator); + UnusedValNo = ClobberValNo = getNextValue(~0U, 0, VNInfoAllocator); ValNoMaps.insert(std::make_pair(I->valno, ClobberValNo)); } @@ -623,6 +626,7 @@ // Insert the clobber interval. IP = addRangeFrom(LiveRange(SubRangeStart, SubRangeEnd, ClobberValNo), IP); + UnusedValNo = 0; } } } From wangmp at apple.com Sat Apr 25 15:47:00 2009 From: wangmp at apple.com (Mon P Wang) Date: Sat, 25 Apr 2009 20:47:00 -0000 Subject: [llvm-commits] [llvm] r70072 - /llvm/trunk/include/llvm/Constants.h Message-ID: <200904252047.n3PKl0g4007787@zion.cs.uiuc.edu> Author: wangmp Date: Sat Apr 25 15:46:59 2009 New Revision: 70072 URL: http://llvm.org/viewvc/llvm-project?rev=70072&view=rev Log: size() should return a size_t; avoids a warning for 64 bit machines. Modified: llvm/trunk/include/llvm/Constants.h Modified: llvm/trunk/include/llvm/Constants.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=70072&r1=70071&r2=70072&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constants.h (original) +++ llvm/trunk/include/llvm/Constants.h Sat Apr 25 15:46:59 2009 @@ -845,7 +845,7 @@ /// size() - The length of this string. /// - unsigned size() const { return StrEnd - StrBegin; } + size_t size() const { return StrEnd - StrBegin; } /// begin() - Pointer to the first byte of the string. /// From isanbard at gmail.com Sat Apr 25 16:06:53 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sat, 25 Apr 2009 21:06:53 -0000 Subject: [llvm-commits] [llvm] r70076 - /llvm/trunk/include/llvm/Constants.h Message-ID: <200904252106.n3PL6rJe008638@zion.cs.uiuc.edu> Author: void Date: Sat Apr 25 16:06:53 2009 New Revision: 70076 URL: http://llvm.org/viewvc/llvm-project?rev=70076&view=rev Log: Use intptr_t. Modified: llvm/trunk/include/llvm/Constants.h Modified: llvm/trunk/include/llvm/Constants.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=70076&r1=70075&r2=70076&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constants.h (original) +++ llvm/trunk/include/llvm/Constants.h Sat Apr 25 16:06:53 2009 @@ -845,7 +845,7 @@ /// size() - The length of this string. /// - size_t size() const { return StrEnd - StrBegin; } + intptr_t size() const { return StrEnd - StrBegin; } /// begin() - Pointer to the first byte of the string. /// From sabre at nondot.org Sat Apr 25 16:11:38 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 21:11:38 -0000 Subject: [llvm-commits] [llvm] r70077 - /llvm/trunk/docs/AliasAnalysis.html Message-ID: <200904252111.n3PLBcOH008819@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 16:11:37 2009 New Revision: 70077 URL: http://llvm.org/viewvc/llvm-project?rev=70077&view=rev Log: Update docs to not mention gcse/loadvn and mention memdep and new stuff. PR3924. Modified: llvm/trunk/docs/AliasAnalysis.html Modified: llvm/trunk/docs/AliasAnalysis.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/AliasAnalysis.html?rev=70077&r1=70076&r2=70077&view=diff ============================================================================== --- llvm/trunk/docs/AliasAnalysis.html (original) +++ llvm/trunk/docs/AliasAnalysis.html Sat Apr 25 16:11:37 2009 @@ -36,7 +36,7 @@
  • Using alias analysis results @@ -537,16 +537,16 @@
    -

    The load-vn pass uses alias analysis to provide value numbering -information for load instructions and pointer values. If your analysis -or transformation can be modeled in a form that uses value numbering -information, you don't have to do anything special to handle load instructions: -just use the load-vn pass, which uses alias analysis.

    +

    The memdep pass uses alias analysis to provide high-level dependence +information about memory-using instructions. This will tell you which store +feeds into a load, for example. It uses caching and other techniques to be +efficient, and is used by Dead Store Elimination, GVN, and memcpy optimizations. +

    @@ -710,7 +710,7 @@ for internal global variables that don't "have their address taken". If a global does not have its address taken, the pass knows that no pointers alias the global. This pass also keeps track of functions that it knows never access -memory or never read memory. This allows certain optimizations (e.g. GCSE) to +memory or never read memory. This allows certain optimizations (e.g. GVN) to eliminate call instructions entirely.

    @@ -855,26 +855,14 @@
    -

    The -load-vn pass uses alias analysis to "value -number" loads and pointers values, which is used by the GCSE pass to -eliminate instructions. The -load-vn pass relies on alias information -and must-alias information. This combination of passes can make the following -transformations:

    - -
      -
    • Redundant load instructions are eliminated.
    • -
    • Load instructions that follow a store to the same location are replaced with -the stored value ("store forwarding").
    • -
    • Pointers values (e.g. formal arguments) that must-alias simpler expressions -(e.g. global variables or the null pointer) are replaced. Note that this -implements transformations like "virtual method resolution", turning indirect -calls into direct calls.
    • -
    +

    These passes use AliasAnalysis information to reason about loads and stores. +

    From sabre at nondot.org Sat Apr 25 16:23:19 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 21:23:19 -0000 Subject: [llvm-commits] [llvm] r70079 - in /llvm/trunk/lib/VMCore: AsmWriter.cpp Verifier.cpp Message-ID: <200904252123.n3PLNJDu009229@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 16:23:19 2009 New Revision: 70079 URL: http://llvm.org/viewvc/llvm-project?rev=70079&view=rev Log: Allow aliasee to be a GEP or bitcast instead of just a bitcast. The real fix for this whole mess is to require the operand of the alias to be a *GlobalValue* (not a general constant, including constant exprs) but allow the operand and the alias type to be unrelated. This fixes PR4066 Modified: llvm/trunk/lib/VMCore/AsmWriter.cpp llvm/trunk/lib/VMCore/Verifier.cpp Modified: llvm/trunk/lib/VMCore/AsmWriter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AsmWriter.cpp?rev=70079&r1=70078&r2=70079&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/AsmWriter.cpp (original) +++ llvm/trunk/lib/VMCore/AsmWriter.cpp Sat Apr 25 16:23:19 2009 @@ -1317,12 +1317,12 @@ Out << ' '; PrintLLVMName(Out, GA); } else { - const ConstantExpr *CE = 0; - if ((CE = dyn_cast(Aliasee)) && - (CE->getOpcode() == Instruction::BitCast)) { - writeOperand(CE, false); - } else - assert(0 && "Unsupported aliasee"); + const ConstantExpr *CE = cast(Aliasee); + // The only valid GEP is an all zero GEP. + assert((CE->getOpcode() == Instruction::BitCast || + CE->getOpcode() == Instruction::GetElementPtr) && + "Unsupported aliasee"); + writeOperand(CE, false); } printInfoComment(*GA); Modified: llvm/trunk/lib/VMCore/Verifier.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=70079&r1=70078&r2=70079&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Verifier.cpp (original) +++ llvm/trunk/lib/VMCore/Verifier.cpp Sat Apr 25 16:23:19 2009 @@ -427,7 +427,9 @@ if (!isa(GA.getAliasee())) { const ConstantExpr *CE = dyn_cast(GA.getAliasee()); - Assert1(CE && CE->getOpcode() == Instruction::BitCast && + Assert1(CE && + (CE->getOpcode() == Instruction::BitCast || + CE->getOpcode() == Instruction::GetElementPtr) && isa(CE->getOperand(0)), "Aliasee should be either GlobalValue or bitcast of GlobalValue", &GA); From sabre at nondot.org Sat Apr 25 16:26:01 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 21:26:01 -0000 Subject: [llvm-commits] [llvm] r70080 - in /llvm/trunk: lib/AsmParser/LLParser.cpp test/Assembler/2009-04-25-AliasGEP.ll Message-ID: <200904252126.n3PLQ1df009312@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 16:26:00 2009 New Revision: 70080 URL: http://llvm.org/viewvc/llvm-project?rev=70080&view=rev Log: testcase and asmparser fix for PR4066 Added: llvm/trunk/test/Assembler/2009-04-25-AliasGEP.ll Modified: llvm/trunk/lib/AsmParser/LLParser.cpp Modified: llvm/trunk/lib/AsmParser/LLParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=70080&r1=70079&r2=70080&view=diff ============================================================================== --- llvm/trunk/lib/AsmParser/LLParser.cpp (original) +++ llvm/trunk/lib/AsmParser/LLParser.cpp Sat Apr 25 16:26:00 2009 @@ -357,7 +357,9 @@ /// ParseAlias: /// ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee /// Aliasee -/// ::= TypeAndValue | 'bitcast' '(' TypeAndValue 'to' Type ')' +/// ::= TypeAndValue +/// ::= 'bitcast' '(' TypeAndValue 'to' Type ')' +/// ::= 'getelementptr' '(' ... ')' /// /// Everything through visibility has already been parsed. /// @@ -379,7 +381,8 @@ Constant *Aliasee; LocTy AliaseeLoc = Lex.getLoc(); - if (Lex.getKind() != lltok::kw_bitcast) { + if (Lex.getKind() != lltok::kw_bitcast && + Lex.getKind() != lltok::kw_getelementptr) { if (ParseGlobalTypeAndValue(Aliasee)) return true; } else { // The bitcast dest type is not present, it is implied by the dest type. Added: llvm/trunk/test/Assembler/2009-04-25-AliasGEP.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/2009-04-25-AliasGEP.ll?rev=70080&view=auto ============================================================================== --- llvm/trunk/test/Assembler/2009-04-25-AliasGEP.ll (added) +++ llvm/trunk/test/Assembler/2009-04-25-AliasGEP.ll Sat Apr 25 16:26:00 2009 @@ -0,0 +1,8 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis +; PR4066 +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" +target triple = "i386-apple-darwin9" + %struct.i2c_device_id = type { } + at w83l785ts_id = internal constant [0 x %struct.i2c_device_id] zeroinitializer, align 1 ; <[0 x %struct.i2c_device_id]*> [#uses=1] + + at __mod_i2c_device_table = alias getelementptr ([0 x %struct.i2c_device_id]* @w83l785ts_id, i32 0, i32 0) ; <%struct.i2c_device_id*> [#uses=0] From sabre at nondot.org Sat Apr 25 17:08:52 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 22:08:52 -0000 Subject: [llvm-commits] [llvm] r70082 - in /llvm/trunk: docs/GettingStarted.html docs/MakefileGuide.html tools/Makefile Message-ID: <200904252208.n3PM8q5g010887@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 17:08:52 2009 New Revision: 70082 URL: http://llvm.org/viewvc/llvm-project?rev=70082&view=rev Log: aDd support for building a subset of the llvm tools, patch by Jeffrey Yasskin! Modified: llvm/trunk/docs/GettingStarted.html llvm/trunk/docs/MakefileGuide.html llvm/trunk/tools/Makefile Modified: llvm/trunk/docs/GettingStarted.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/GettingStarted.html?rev=70082&r1=70081&r2=70082&view=diff ============================================================================== --- llvm/trunk/docs/GettingStarted.html (original) +++ llvm/trunk/docs/GettingStarted.html Sat Apr 25 17:08:52 2009 @@ -327,9 +327,9 @@

    Note that you will need about 1-3 GB of space for a full LLVM build in Debug mode, depending on the system (it is so large because of all the debugging information and the fact that the libraries are statically linked into multiple -tools). If you do not need many of the tools and you are space-conscious, -you can disable them individually in llvm/tools/Makefile. The Release -build requires considerably less space.

    +tools). If you do not need many of the tools and you are space-conscious, you +can pass ONLY_TOOLS="tools you need" to make. The Release build +requires considerably less space.

    The LLVM suite may compile on other platforms, but it is not guaranteed to do so. If compilation is successful, the LLVM utilities should be Modified: llvm/trunk/docs/MakefileGuide.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/MakefileGuide.html?rev=70082&r1=70081&r2=70082&view=diff ============================================================================== --- llvm/trunk/docs/MakefileGuide.html (original) +++ llvm/trunk/docs/MakefileGuide.html Sat Apr 25 17:08:52 2009 @@ -841,6 +841,8 @@

    MKDIR(defaulted)
    Specifies the path to the mkdir tool that creates directories.
    +
    ONLY_TOOLS
    +
    If set, specifies the list of tools to build.
    PLATFORMSTRIPOPTS
    The options to provide to the linker to specify that a stripped (no symbols) executable should be built.
    Modified: llvm/trunk/tools/Makefile URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/Makefile?rev=70082&r1=70081&r2=70082&view=diff ============================================================================== --- llvm/trunk/tools/Makefile (original) +++ llvm/trunk/tools/Makefile Sat Apr 25 17:08:52 2009 @@ -22,6 +22,12 @@ lli gccas gccld llvm-extract llvm-db \ bugpoint llvm-bcanalyzer llvm-stub llvmc +# Let users override the set of tools to build from the command line. +ifdef ONLY_TOOLS + OPTIONAL_PARALLEL_DIRS := + PARALLEL_DIRS := $(ONLY_TOOLS) +endif + include $(LEVEL)/Makefile.config ifeq ($(ENABLE_PIC),1) From clattner at apple.com Sat Apr 25 17:09:14 2009 From: clattner at apple.com (Chris Lattner) Date: Sat, 25 Apr 2009 15:09:14 -0700 Subject: [llvm-commits] ONLY_TOOLS make variable to specify tools to build from the command line In-Reply-To: References: Message-ID: <4A5965C0-AC1A-4BE0-A2EC-B512E45B6DBE@apple.com> On Apr 23, 2009, at 11:57 AM, Jeffrey Yasskin wrote: > Here's the patch I was talking about on the IRC channel, to let me > build fewer tools without hacking the Makefile. Looks great, applied! http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20090420/076700.html -Chris From sabre at nondot.org Sat Apr 25 17:10:07 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 22:10:07 -0000 Subject: [llvm-commits] [llvm] r70083 - /llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h Message-ID: <200904252210.n3PMA7hf010979@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 17:10:06 2009 New Revision: 70083 URL: http://llvm.org/viewvc/llvm-project?rev=70083&view=rev Log: improve documentation around memory lifetimes, patch by Jeffrey Yasskin! Modified: llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h Modified: llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h?rev=70083&r1=70082&r2=70083&view=diff ============================================================================== --- llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h (original) +++ llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h Sat Apr 25 17:10:06 2009 @@ -186,7 +186,8 @@ /// at the specified location. This is used internally as functions are JIT'd /// and as global variables are laid out in memory. It can and should also be /// used by clients of the EE that want to have an LLVM global overlay - /// existing data in memory. + /// existing data in memory. After adding a mapping for GV, you must not + /// destroy it until you've removed the mapping. void addGlobalMapping(const GlobalValue *GV, void *Addr); /// clearAllGlobalMappings - Clear all global mappings and start over again @@ -210,19 +211,29 @@ void *getPointerToGlobalIfAvailable(const GlobalValue *GV); /// getPointerToGlobal - This returns the address of the specified global - /// value. This may involve code generation if it's a function. + /// value. This may involve code generation if it's a function. After + /// getting a pointer to GV, it and all globals it transitively refers to have + /// been passed to addGlobalMapping. You must clear the mapping for each + /// referred-to global before destroying it. If a referred-to global RTG is a + /// function and this ExecutionEngine is a JIT compiler, calling + /// updateGlobalMapping(RTG, 0) will leak the function's machine code, so you + /// should call freeMachineCodeForFunction(RTG) instead. Note that + /// optimizations can move and delete non-external GlobalValues without + /// notifying the ExecutionEngine. /// void *getPointerToGlobal(const GlobalValue *GV); /// getPointerToFunction - The different EE's represent function bodies in /// different ways. They should each implement this to say what a function - /// pointer should look like. + /// pointer should look like. See getPointerToGlobal for the requirements on + /// destroying F and any GlobalValues it refers to. /// virtual void *getPointerToFunction(Function *F) = 0; /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use - /// a stub to implement lazy compilation if available. + /// a stub to implement lazy compilation if available. See getPointerToGlobal + /// for the requirements on destroying F and any GlobalValues it refers to. /// virtual void *getPointerToFunctionOrStub(Function *F) { // Default implementation, just codegen the function. @@ -255,7 +266,8 @@ /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the - /// Emitter. + /// Emitter. See getPointerToGlobal for the requirements on destroying GV and + /// any GlobalValues it refers to. virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { return getPointerToGlobal((GlobalValue*)GV); } From clattner at apple.com Sat Apr 25 17:10:25 2009 From: clattner at apple.com (Chris Lattner) Date: Sat, 25 Apr 2009 15:10:25 -0700 Subject: [llvm-commits] Documentation for GlobalValue lifetime requirements around an ExecutionEngine In-Reply-To: References: Message-ID: <023DEB7B-2D23-46B2-81EB-F48795ED02DD@apple.com> On Apr 22, 2009, at 10:32 AM, Jeffrey Yasskin wrote: > This is an attempt to describe how users have to handle deleting > GlobalValues that they've emitted code for. I'm not sure I have the > requirements right, so please double-check them. > > I believe that there's no way to free the memory that > getOrEmitGlobalVariable allocates, but I haven't documented that on > the theory that it's a bug. > > I also haven't mentioned the requirement that no thread, including the > current one, is inside a function's machine code when you call > recompileAndRelinkFunction(that_function). I'm not sure if it's > obvious. Applied, thanks! http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20090420/076702.html -Chris From sabre at nondot.org Sat Apr 25 17:14:07 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 22:14:07 -0000 Subject: [llvm-commits] [llvm] r70084 - in /llvm/trunk: include/llvm/Support/TypeBuilder.h unittests/Support/TypeBuilderTest.cpp Message-ID: <200904252214.n3PME7Cu011188@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 17:14:04 2009 New Revision: 70084 URL: http://llvm.org/viewvc/llvm-project?rev=70084&view=rev Log: Add a new TypeBuilder helper class, which eases making LLVM IR types. Patch by Jeffrey Yasskin! Added: llvm/trunk/include/llvm/Support/TypeBuilder.h llvm/trunk/unittests/Support/TypeBuilderTest.cpp Added: llvm/trunk/include/llvm/Support/TypeBuilder.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/TypeBuilder.h?rev=70084&view=auto ============================================================================== --- llvm/trunk/include/llvm/Support/TypeBuilder.h (added) +++ llvm/trunk/include/llvm/Support/TypeBuilder.h Sat Apr 25 17:14:04 2009 @@ -0,0 +1,463 @@ +//===---- llvm/Support/TypeBuilder.h - Builder for LLVM types ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the TypeBuilder class, which is used as a convenient way to +// create LLVM types with a consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPEBUILDER_H +#define LLVM_SUPPORT_TYPEBUILDER_H + +#include "llvm/DerivedTypes.h" + +namespace llvm { + +/// TypeBuilder - This provides a uniform API for looking up types +/// known at compile time. To support cross-compilation, we define a +/// series of tag types in the llvm::types namespace, like i, +/// ieee_float, ppc_fp128, etc. TypeBuilder allows T to be +/// any of these, a native C type (whose size may depend on the host +/// compiler), or a pointer, function, or struct type built out of +/// these. TypeBuilder removes native C types from this set +/// to guarantee that its result is suitable for cross-compilation. +/// We define the primitive types, pointer types, and functions up to +/// 5 arguments here, but to use this class with your own types, +/// you'll need to specialize it. For example, say you want to call a +/// function defined externally as: +/// +/// struct MyType { +/// int32 a; +/// int32 *b; +/// void *array[1]; // Intended as a flexible array. +/// }; +/// int8 AFunction(struct MyType *value); +/// +/// You'll want to use +/// Function::Create(TypeBuilder(MyType*)>::get(), ...) +/// to declare the function, but when you first try this, your compiler will +/// complain that TypeBuilder::get() doesn't exist. To fix this, write: +/// +/// namespace llvm { +/// using types::i; +/// template class TypeBuilder { +/// public: +/// static const StructType *get() { +/// // Using the static result variable ensures that the type is +/// // only looked up once. +/// static const StructType *const result = StructType::get( +/// TypeBuilder, xcompile>::get(), +/// TypeBuilder*, xcompile>::get(), +/// TypeBuilder*[], xcompile>::get(), +/// NULL); +/// return result; +/// } +/// +/// // You may find this a convenient place to put some constants +/// // to help with getelementptr. They don't have any effect on +/// // the operation of TypeBuilder. +/// enum Fields { +/// FIELD_A, +/// FIELD_B, +/// FIELD_ARRAY +/// }; +/// } +/// } // namespace llvm +/// +/// Using the static result variable ensures that the type is only looked up +/// once. +/// +/// TypeBuilder cannot handle recursive types or types you only know at runtime. +/// If you try to give it a recursive type, it will deadlock, infinitely +/// recurse, or throw a recursive_init exception. +template class TypeBuilder {}; + +// Types for use with cross-compilable TypeBuilders. These correspond +// exactly with an LLVM-native type. +namespace types { +/// i corresponds to the LLVM IntegerType with N bits. +template class i {}; + +// The following classes represent the LLVM floating types. +class ieee_float {}; +class ieee_double {}; +class x86_fp80 {}; +class fp128 {}; +class ppc_fp128 {}; +} // namespace types + +// LLVM doesn't have const or volatile types. +template class TypeBuilder + : public TypeBuilder {}; +template class TypeBuilder + : public TypeBuilder {}; +template class TypeBuilder + : public TypeBuilder {}; + +// Pointers +template class TypeBuilder { +public: + static const PointerType *get() { + static const PointerType *const result = + PointerType::getUnqual(TypeBuilder::get()); + return result; + } +}; + +/// There is no support for references +template class TypeBuilder {}; + +// Arrays +template class TypeBuilder { +public: + static const ArrayType *get() { + static const ArrayType *const result = + ArrayType::get(TypeBuilder::get(), N); + return result; + } +}; +/// LLVM uses an array of length 0 to represent an unknown-length array. +template class TypeBuilder { +public: + static const ArrayType *get() { + static const ArrayType *const result = + ArrayType::get(TypeBuilder::get(), 0); + return result; + } +}; + +// Define the C integral types only for TypeBuilder. +// +// C integral types do not have a defined size. It would be nice to use the +// stdint.h-defined typedefs that do have defined sizes, but we'd run into the +// following problem: +// +// On an ILP32 machine, stdint.h might define: +// +// typedef int int32_t; +// typedef long long int64_t; +// typedef long size_t; +// +// If we defined TypeBuilder and TypeBuilder, then any use of +// TypeBuilder would fail. We couldn't define TypeBuilder in +// addition to the defined-size types because we'd get duplicate definitions on +// platforms where stdint.h instead defines: +// +// typedef int int32_t; +// typedef long long int64_t; +// typedef int size_t; +// +// So we define all the primitive C types and nothing else. +#define DEFINE_INTEGRAL_TYPEBUILDER(T) \ +template<> class TypeBuilder { \ +public: \ + static const IntegerType *get() { \ + static const IntegerType *const result = \ + IntegerType::get(sizeof(T) * CHAR_BIT); \ + return result; \ + } \ +}; \ +template<> class TypeBuilder { \ + /* We provide a definition here so users don't accidentally */ \ + /* define these types to work. */ \ +} +DEFINE_INTEGRAL_TYPEBUILDER(char); +DEFINE_INTEGRAL_TYPEBUILDER(signed char); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned char); +DEFINE_INTEGRAL_TYPEBUILDER(short); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned short); +DEFINE_INTEGRAL_TYPEBUILDER(int); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned int); +DEFINE_INTEGRAL_TYPEBUILDER(long); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned long); +#ifdef _MSC_VER +DEFINE_INTEGRAL_TYPEBUILDER(__int64); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned __int64); +#else /* _MSC_VER */ +DEFINE_INTEGRAL_TYPEBUILDER(long long); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned long long); +#endif /* _MSC_VER */ +#undef DEFINE_INTEGRAL_TYPEBUILDER + +template +class TypeBuilder, cross> { +public: + static const IntegerType *get() { + static const IntegerType *const result = IntegerType::get(num_bits); + return result; + } +}; + +template<> class TypeBuilder { +public: + static const Type *get() { + return Type::FloatTy; + } +}; +template<> class TypeBuilder {}; + +template<> class TypeBuilder { +public: + static const Type *get() { + return Type::DoubleTy; + } +}; +template<> class TypeBuilder {}; + +template class TypeBuilder { +public: + static const Type *get() { return Type::FloatTy; } +}; +template class TypeBuilder { +public: + static const Type *get() { return Type::DoubleTy; } +}; +template class TypeBuilder { +public: + static const Type *get() { return Type::X86_FP80Ty; } +}; +template class TypeBuilder { +public: + static const Type *get() { return Type::FP128Ty; } +}; +template class TypeBuilder { +public: + static const Type *get() { return Type::PPC_FP128Ty; } +}; + +template class TypeBuilder { +public: + static const Type *get() { + return Type::VoidTy; + } +}; + +/// void* is disallowed in LLVM types, but it occurs often enough in C code that +/// we special case it. +template<> class TypeBuilder + : public TypeBuilder*, false> {}; + +template class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + return FunctionType::get(TypeBuilder::get(), params, false); + } +}; +template class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(1); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, false); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(2); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, false); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(3); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, false); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(4); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, false); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(5); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, false); + } +}; + +template class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + return FunctionType::get(TypeBuilder::get(), params, true); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(1); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, true); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(2); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, true); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(3); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, true); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(4); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, true); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get() { + static const FunctionType *const result = create(); + return result; + } + +private: + static const FunctionType *create() { + std::vector params; + params.reserve(5); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + params.push_back(TypeBuilder::get()); + return FunctionType::get(TypeBuilder::get(), params, true); + } +}; + +} // namespace llvm + +#endif Added: llvm/trunk/unittests/Support/TypeBuilderTest.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/TypeBuilderTest.cpp?rev=70084&view=auto ============================================================================== --- llvm/trunk/unittests/Support/TypeBuilderTest.cpp (added) +++ llvm/trunk/unittests/Support/TypeBuilderTest.cpp Sat Apr 25 17:14:04 2009 @@ -0,0 +1,233 @@ +//===- llvm/unittest/Support/TypeBuilderTest.cpp - TypeBuilder tests -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/TypeBuilder.h" + +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(TypeBuilderTest, Void) { + EXPECT_EQ(Type::VoidTy, (TypeBuilder::get())); + EXPECT_EQ(Type::VoidTy, (TypeBuilder::get())); + // Special case for C compatibility: + EXPECT_EQ(PointerType::getUnqual(Type::Int8Ty), + (TypeBuilder::get())); +} + +TEST(TypeBuilderTest, HostIntegers) { + EXPECT_EQ(Type::Int8Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::Int8Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::Int16Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::Int16Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::Int32Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::Int32Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::Int64Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::Int64Ty, (TypeBuilder::get())); + + EXPECT_EQ(IntegerType::get(sizeof(size_t) * CHAR_BIT), + (TypeBuilder::get())); + EXPECT_EQ(IntegerType::get(sizeof(ptrdiff_t) * CHAR_BIT), + (TypeBuilder::get())); +} + +TEST(TypeBuilderTest, CrossCompilableIntegers) { + EXPECT_EQ(IntegerType::get(1), (TypeBuilder, true>::get())); + EXPECT_EQ(IntegerType::get(1), (TypeBuilder, false>::get())); + EXPECT_EQ(IntegerType::get(72), (TypeBuilder, true>::get())); + EXPECT_EQ(IntegerType::get(72), (TypeBuilder, false>::get())); +} + +TEST(TypeBuilderTest, Float) { + EXPECT_EQ(Type::FloatTy, (TypeBuilder::get())); + EXPECT_EQ(Type::DoubleTy, (TypeBuilder::get())); + // long double isn't supported yet. + EXPECT_EQ(Type::FloatTy, (TypeBuilder::get())); + EXPECT_EQ(Type::FloatTy, (TypeBuilder::get())); + EXPECT_EQ(Type::DoubleTy, (TypeBuilder::get())); + EXPECT_EQ(Type::DoubleTy, (TypeBuilder::get())); + EXPECT_EQ(Type::X86_FP80Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::X86_FP80Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::FP128Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::FP128Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::PPC_FP128Ty, (TypeBuilder::get())); + EXPECT_EQ(Type::PPC_FP128Ty, (TypeBuilder::get())); +} + +TEST(TypeBuilderTest, Derived) { + EXPECT_EQ(PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)), + (TypeBuilder::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 7), + (TypeBuilder::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 0), + (TypeBuilder::get())); + + EXPECT_EQ(PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)), + (TypeBuilder**, false>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 7), + (TypeBuilder[7], false>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 0), + (TypeBuilder[], false>::get())); + + EXPECT_EQ(PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)), + (TypeBuilder**, true>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 7), + (TypeBuilder[7], true>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 0), + (TypeBuilder[], true>::get())); + + + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder::get())); + + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder, false>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder, false>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder, false>::get())); + + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder, true>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder, true>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder, true>::get())); + + EXPECT_EQ(PointerType::getUnqual(Type::Int8Ty), + (TypeBuilder::get())); +} + +TEST(TypeBuilderTest, Functions) { + std::vector params; + EXPECT_EQ(FunctionType::get(Type::VoidTy, params, false), + (TypeBuilder::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder::get())); + params.push_back(TypeBuilder::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder::get())); + params.push_back(TypeBuilder::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder::get())); + params.push_back(TypeBuilder::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder::get())); + params.push_back(TypeBuilder::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder::get())); + params.push_back(TypeBuilder::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder::get())); +} + +class MyType { + int a; + int *b; + void *array[1]; +}; + +class MyPortableType { + int32_t a; + int32_t *b; + void *array[1]; +}; + +} // anonymous namespace + +namespace llvm { +template class TypeBuilder { +public: + static const StructType *get() { + // Using the static result variable ensures that the type is + // only looked up once. + static const StructType *const result = StructType::get( + TypeBuilder::get(), + TypeBuilder::get(), + TypeBuilder::get(), + NULL); + return result; + } + + // You may find this a convenient place to put some constants + // to help with getelementptr. They don't have any effect on + // the operation of TypeBuilder. + enum Fields { + FIELD_A, + FIELD_B, + FIELD_ARRAY + }; +}; + +template class TypeBuilder { +public: + static const StructType *get() { + // Using the static result variable ensures that the type is + // only looked up once. + static const StructType *const result = StructType::get( + TypeBuilder, cross>::get(), + TypeBuilder*, cross>::get(), + TypeBuilder*[], cross>::get(), + NULL); + return result; + } + + // You may find this a convenient place to put some constants + // to help with getelementptr. They don't have any effect on + // the operation of TypeBuilder. + enum Fields { + FIELD_A, + FIELD_B, + FIELD_ARRAY + }; +}; +} // namespace llvm +namespace { + +TEST(TypeBuilderTest, Extensions) { + EXPECT_EQ(PointerType::getUnqual(StructType::get( + TypeBuilder::get(), + TypeBuilder::get(), + TypeBuilder::get(), + NULL)), + (TypeBuilder::get())); + EXPECT_EQ(PointerType::getUnqual(StructType::get( + TypeBuilder, false>::get(), + TypeBuilder*, false>::get(), + TypeBuilder*[], false>::get(), + NULL)), + (TypeBuilder::get())); + EXPECT_EQ(PointerType::getUnqual(StructType::get( + TypeBuilder, false>::get(), + TypeBuilder*, false>::get(), + TypeBuilder*[], false>::get(), + NULL)), + (TypeBuilder::get())); +} + +} // anonymous namespace From clattner at apple.com Sat Apr 25 17:15:19 2009 From: clattner at apple.com (Chris Lattner) Date: Sat, 25 Apr 2009 15:15:19 -0700 Subject: [llvm-commits] TypeBuilder helper class In-Reply-To: References: <5F5A9B7F-1967-4D07-9D74-20466088C123@apple.com> Message-ID: On Apr 12, 2009, at 5:16 PM, Jeffrey Yasskin wrote: > On Thu, Apr 9, 2009 at 11:38 PM, Chris Lattner > wrote: >> >> On Apr 9, 2009, at 9:40 AM, Jeffrey Yasskin wrote: >> >>> >>> I think I see how to define TypeBuilder>> restrict_to_cross_compilable_types> so that TypeBuilder>> true> >>> fails to compile but TypeBuilder, false> succeeds, >>> without duplicating code. Could you confirm that that's along the >>> lines of what you want implemented before I waste time implementing >>> it? Also, what's the right spelling for "sometype"? I'd vote for >>> llvm::types::i or something similar. >>> >> >> Sounds great to me! > > Ok, here's the new version. I'm not entirely happy with using a bool > for this decision since it makes user code harder to read. I could use > an enum or distinct subtypes, but then I'd need names. "Host" seems to > work for the version that accepts types like 'size_t', but > "CrossCompilable" seems too long for the version that doesn't. > Thoughts? This looks great! Can you please add some mention of this to the programmer's manual? http://llvm.org/docs/ProgrammersManual.html Perhaps a "how to create types" entry in the "Helpful Hints for Common Operations" section. Applied here: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20090420/076704.html Thanks Jeffrey! -Chris From sabre at nondot.org Sat Apr 25 17:20:49 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 22:20:49 -0000 Subject: [llvm-commits] [llvm] r70085 - /llvm/trunk/test/Assembler/getelementptr.ll Message-ID: <200904252220.n3PMKoZZ011393@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 17:20:49 2009 New Revision: 70085 URL: http://llvm.org/viewvc/llvm-project?rev=70085&view=rev Log: add testcase for strange types of gep indices Added: llvm/trunk/test/Assembler/getelementptr.ll Added: llvm/trunk/test/Assembler/getelementptr.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/getelementptr.ll?rev=70085&view=auto ============================================================================== --- llvm/trunk/test/Assembler/getelementptr.ll (added) +++ llvm/trunk/test/Assembler/getelementptr.ll Sat Apr 25 17:20:49 2009 @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis + +;; Verify that i16 indices work. + at x = external global {i32, i32} + at y = global i32* getelementptr ({i32, i32}* @x, i16 42, i32 0) + +; see if i92 indices work too. +define i32 *@test({i32, i32}* %t, i92 %n) { + %B = getelementptr {i32, i32}* %t, i92 %n, i32 0 + ret i32* %B +} + From clattner at apple.com Sat Apr 25 17:22:17 2009 From: clattner at apple.com (Chris Lattner) Date: Sat, 25 Apr 2009 15:22:17 -0700 Subject: [llvm-commits] [llvm] r69946 - in /llvm/trunk: docs/LangRef.html lib/Transforms/Scalar/InstructionCombining.cpp lib/VMCore/Type.cpp In-Reply-To: <200904240237.n3O2bsqj032157@zion.cs.uiuc.edu> References: <200904240237.n3O2bsqj032157@zion.cs.uiuc.edu> Message-ID: <455CA6D2-CDBA-4A16-80E2-DF7F898948A7@apple.com> On Apr 23, 2009, at 7:37 PM, Sanjiv Gupta wrote: > Author: sgupta > Date: Thu Apr 23 21:37:54 2009 > New Revision: 69946 > > URL: http://llvm.org/viewvc/llvm-project?rev=69946&view=rev > Log: > Allow i16 type indices to gep. Hi Sanjiv, It looks like you've made all integer sized indices valid for array indexes, see this testcase: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20090420/076706.html I think this is a fine thing to do, but if you're going to do that, shouldn't SequentialType::indexValid return true for any integer type? -Chris > > > Modified: > llvm/trunk/docs/LangRef.html > llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > llvm/trunk/lib/VMCore/Type.cpp > > Modified: llvm/trunk/docs/LangRef.html > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=69946&r1=69945&r2=69946&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/docs/LangRef.html (original) > +++ llvm/trunk/docs/LangRef.html Thu Apr 23 21:37:54 2009 > @@ -3629,7 +3629,8 @@ >

    The type of each index argument depends on the type it is > indexing into. > When indexing into a (packed) structure, only i32 integer > constants are allowed. When indexing into an array, pointer > or vector, > -only integers of 32 or 64 bits are allowed (also non-constants). 32- > bit values > +only integers of 16, 32 or 64 bits are allowed (also non-constants). > 16-bit > +values will be sign extended to 32-bits if required, and 32-bit > values > will be sign extended to 64-bits if required.

    > >

    For example, let's consider a C code fragment and how it gets > @@ -3717,6 +3718,8 @@ > %vptr = getelementptr {i32, <2 x i8>}* %svptr, i64 0, i32 > 1, i32 1 > ; yields i8*:eptr > %eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1 > + ; yields i16*:iptr > + %iptr = getelementptr [10 x i16]* @arr, i16 0, i16 0 > > > > > Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69946&r1=69945&r2=69946&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > (original) > +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Thu > Apr 23 21:37:54 2009 > @@ -10695,12 +10695,7 @@ > gep_type_iterator GTI = gep_type_begin(GEP); > for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); > i != e; ++i, ++GTI) { > - // Before trying to eliminate/introduce cast/ext/trunc to make > - // indices as pointer types, make sure that the pointer size > - // makes a valid sequential index. > - const SequentialType *ST = dyn_cast(*GTI); > - Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); > - if (ST && ST->indexValid(PtrTypeVal)) { > + if (isa(*GTI)) { > if (CastInst *CI = dyn_cast(*i)) { > if (CI->getOpcode() == Instruction::ZExt || > CI->getOpcode() == Instruction::SExt) { > > Modified: llvm/trunk/lib/VMCore/Type.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=69946&r1=69945&r2=69946&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/VMCore/Type.cpp (original) > +++ llvm/trunk/lib/VMCore/Type.cpp Thu Apr 23 21:37:54 2009 > @@ -1411,7 +1411,8 @@ > > bool SequentialType::indexValid(const Value *V) const { > if (const IntegerType *IT = dyn_cast(V->getType())) > - return IT->getBitWidth() == 32 || IT->getBitWidth() == 64; > + return IT->getBitWidth() == 16 || IT->getBitWidth() == 32 || > + IT->getBitWidth() == 64; > return false; > } > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From sabre at nondot.org Sat Apr 25 17:24:49 2009 From: sabre at nondot.org (Chris Lattner) Date: Sat, 25 Apr 2009 22:24:49 -0000 Subject: [llvm-commits] [llvm] r70087 - /llvm/trunk/docs/GettingStarted.html Message-ID: <200904252224.n3PMOndT011547@zion.cs.uiuc.edu> Author: lattner Date: Sat Apr 25 17:24:49 2009 New Revision: 70087 URL: http://llvm.org/viewvc/llvm-project?rev=70087&view=rev Log: improve documentation on build configurations, patch by Josef Eisl! Modified: llvm/trunk/docs/GettingStarted.html Modified: llvm/trunk/docs/GettingStarted.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/GettingStarted.html?rev=70087&r1=70086&r2=70087&view=diff ============================================================================== --- llvm/trunk/docs/GettingStarted.html (original) +++ llvm/trunk/docs/GettingStarted.html Sat Apr 25 17:24:49 2009 @@ -687,7 +687,7 @@

    If you have access to our Subversion repository, you can get a fresh copy of -the entire source code. All you need to do is check it out from Subvresion as +the entire source code. All you need to do is check it out from Subversion as follows:

      @@ -708,6 +708,7 @@ subdirectories of the 'tags' directory:

        +
      • Release 2.5: RELEASE_25
      • Release 2.4: RELEASE_24
      • Release 2.3: RELEASE_23
      • Release 2.2: RELEASE_22
      • @@ -848,9 +849,11 @@
        --enable-optimized
        - Enables optimized compilation by default (debugging symbols are removed - and GCC optimization flags are enabled). The default is to use an - unoptimized build (also known as a debug build). + Enables optimized compilation (debugging symbols are removed + and GCC optimization flags are enabled). Note that this is the default + setting if you are using the LLVM distribution. The default behavior + of an Subversion checkout is to use an unoptimized build (also known as a + debug build).

        --enable-debug-runtime
        @@ -918,10 +921,12 @@
        Debug Builds
        - These builds are the default when one types gmake (unless the - --enable-optimized option was used during configuration). The - build system will compile the tools and libraries with debugging - information. + These builds are the default when one is using an Subversion checkout and + types gmake (unless the --enable-optimized option was + used during configuration). The build system will compile the tools and + libraries with debugging information. To get a Debug Build using the + LLVM distribution the --disable-optimized option must be passed + to configure.

        Release (Optimized) Builds @@ -931,6 +936,7 @@ gmake command line. For these builds, the build system will compile the tools and libraries with GCC optimizations enabled and strip debugging information from the libraries and executables it generates. + Note that Release Builds are default when using an LLVM distribution.

        Profile Builds @@ -1007,6 +1013,11 @@
        Perform a Release (Optimized) build without assertions enabled.

        + +
        gmake ENABLE_OPTIMIZED=0 +
        + Perform a Debug build. +

        gmake ENABLE_PROFILING=1
        From sanjiv.gupta at microchip.com Sun Apr 26 02:41:01 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Sun, 26 Apr 2009 13:11:01 +0530 Subject: [llvm-commits] [llvm] r69946 - in /llvm/trunk: docs/LangRef.html lib/Transforms/Scalar/InstructionCombining.cpp lib/VMCore/Type.cpp In-Reply-To: <455CA6D2-CDBA-4A16-80E2-DF7F898948A7@apple.com> References: <200904240237.n3O2bsqj032157@zion.cs.uiuc.edu> <455CA6D2-CDBA-4A16-80E2-DF7F898948A7@apple.com> Message-ID: <49F4100D.50807@microchip.com> Chris Lattner wrote: > On Apr 23, 2009, at 7:37 PM, Sanjiv Gupta wrote: >> Author: sgupta >> Date: Thu Apr 23 21:37:54 2009 >> New Revision: 69946 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=69946&view=rev >> Log: >> Allow i16 type indices to gep. > > Hi Sanjiv, > > It looks like you've made all integer sized indices valid for array > indexes, see this testcase: > http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20090420/076706.html > > > I think this is a fine thing to do, but if you're going to do that, > shouldn't SequentialType::indexValid return true for any integer type? > > -Chris I think the assembler and dis-assembler never bothered to call sequentialType::indexValid. This test case always used to work. Its only the clang and the opt that check the validity. But anyways there is a disconnect here between various tools and the documentation. I think we should allow all types of integer indices and change the documentation and code accordingly. I will do that. Meanwhile, do you think we might have a similar case for structType::indexValid. Adding a test case for that as well will be a good idea. Thanks, - Sanjiv > >> >> >> Modified: >> llvm/trunk/docs/LangRef.html >> llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> llvm/trunk/lib/VMCore/Type.cpp >> >> Modified: llvm/trunk/docs/LangRef.html >> URL: >> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=69946&r1=69945&r2=69946&view=diff >> >> >> ============================================================================== >> >> --- llvm/trunk/docs/LangRef.html (original) >> +++ llvm/trunk/docs/LangRef.html Thu Apr 23 21:37:54 2009 >> @@ -3629,7 +3629,8 @@ >>

        The type of each index argument depends on the type it is indexing >> into. >> When indexing into a (packed) structure, only i32 integer >> constants are allowed. When indexing into an array, pointer >> or vector, >> -only integers of 32 or 64 bits are allowed (also non-constants). >> 32-bit values >> +only integers of 16, 32 or 64 bits are allowed (also >> non-constants).16-bit >> +values will be sign extended to 32-bits if required, and 32-bit values >> will be sign extended to 64-bits if required.

        >> >>

        For example, let's consider a C code fragment and how it gets >> @@ -3717,6 +3718,8 @@ >> %vptr = getelementptr {i32, <2 x i8>}* %svptr, i64 0, i32 >> 1, i32 1 >> ; yields i8*:eptr >> %eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1 >> + ; yields i16*:iptr >> + %iptr = getelementptr [10 x i16]* @arr, i16 0, i16 0 >> >>

    >> >> >> Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=69946&r1=69945&r2=69946&view=diff >> >> >> ============================================================================== >> >> --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) >> +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Thu Apr >> 23 21:37:54 2009 >> @@ -10695,12 +10695,7 @@ >> gep_type_iterator GTI = gep_type_begin(GEP); >> for (User::op_iterator i = GEP.op_begin() + 1, e = GEP.op_end(); >> i != e; ++i, ++GTI) { >> - // Before trying to eliminate/introduce cast/ext/trunc to make >> - // indices as pointer types, make sure that the pointer size >> - // makes a valid sequential index. >> - const SequentialType *ST = dyn_cast(*GTI); >> - Value *PtrTypeVal = Constant::getNullValue(TD->getIntPtrType()); >> - if (ST && ST->indexValid(PtrTypeVal)) { >> + if (isa(*GTI)) { >> if (CastInst *CI = dyn_cast(*i)) { >> if (CI->getOpcode() == Instruction::ZExt || >> CI->getOpcode() == Instruction::SExt) { >> >> Modified: llvm/trunk/lib/VMCore/Type.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=69946&r1=69945&r2=69946&view=diff >> >> >> ============================================================================== >> >> --- llvm/trunk/lib/VMCore/Type.cpp (original) >> +++ llvm/trunk/lib/VMCore/Type.cpp Thu Apr 23 21:37:54 2009 >> @@ -1411,7 +1411,8 @@ >> >> bool SequentialType::indexValid(const Value *V) const { >> if (const IntegerType *IT = dyn_cast(V->getType())) >> - return IT->getBitWidth() == 32 || IT->getBitWidth() == 64; >> + return IT->getBitWidth() == 16 || IT->getBitWidth() == 32 || >> + IT->getBitWidth() == 64; >> return false; >> } >> >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From isanbard at gmail.com Sun Apr 26 04:12:45 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 09:12:45 -0000 Subject: [llvm-commits] [llvm] r70117 - /llvm/tags/Apple/llvmCore-2107.1/ Message-ID: <200904260912.n3Q9CjQj010625@zion.cs.uiuc.edu> Author: void Date: Sun Apr 26 04:12:31 2009 New Revision: 70117 URL: http://llvm.org/viewvc/llvm-project?rev=70117&view=rev Log: Creating llvmCore-2107.1 from Dib. Added: llvm/tags/Apple/llvmCore-2107.1/ - copied from r70116, llvm/branches/Apple/Dib/ From isanbard at gmail.com Sun Apr 26 04:13:16 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 09:13:16 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r70118 - /llvm-gcc-4.2/tags/Apple/llvmgcc42-2107.1/ Message-ID: <200904260913.n3Q9DG1C010647@zion.cs.uiuc.edu> Author: void Date: Sun Apr 26 04:13:16 2009 New Revision: 70118 URL: http://llvm.org/viewvc/llvm-project?rev=70118&view=rev Log: Creating llvmgcc42-2107.1 from Dib. Added: llvm-gcc-4.2/tags/Apple/llvmgcc42-2107.1/ - copied from r70117, llvm-gcc-4.2/branches/Apple/Dib/ From stoklund at 2pi.dk Sun Apr 26 10:21:07 2009 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Sun, 26 Apr 2009 17:21:07 +0200 Subject: [llvm-commits] [PATCH] Prevent illegal joins of physical and virtual registers Message-ID: This is my second attempt at verifying register classes when coalescing physical and virtual registers. The first attempt completely missed the issue of subregisters being joined. I have attached two patches: targetregclass.patch: Change the static function getSubRegisterRegClass in ScheduleDagSDNodesEmit.cpp to a method on TargetRegisterClass. The method is needed by the next patch. coalesce-phys-virt.patch: Verify register classes when joining physical and virtual registers. This time take into account all the weird subreg combinations that are possible. Please note that this patch causes a number of failures in the CodeGen/ X86 test suite. That is because X86RegisterInfo.td contains inconsistent information about subregister classes. I am submitting a patch to the X86 backend that fixes this. With the X86 patch, this patch passes "make check". -------------- next part -------------- A non-text attachment was scrubbed... Name: coalesce-phys-virt.patch Type: application/octet-stream Size: 3639 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090426/409ac9e3/attachment.obj -------------- next part -------------- A non-text attachment was scrubbed... Name: targetregclass-subreg.patch Type: application/octet-stream Size: 3340 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090426/409ac9e3/attachment-0001.obj From stoklund at 2pi.dk Sun Apr 26 10:21:09 2009 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Sun, 26 Apr 2009 17:21:09 +0200 Subject: [llvm-commits] [PATCH] Add GR8_H register class to X86 backend Message-ID: <74F36AB3-29C6-4FB0-8956-6F3CA337D62C@2pi.dk> X86RegisterInfo.td declares these register classes: def GR8_ : RegisterClass<"X86", [i8], 8, [AL, CL, DL, BL]> { } def GR16_ : RegisterClass<"X86", [i16], 16, [AX, CX, DX, BX]> { let SubRegClassList = [GR8_, GR8_]; } The SubRegClassList asserts that EXTRACT_SUBREG GR16_, 2 yields a GR8_ register. This is inconsistent with the actual SubRegSet: def : SubRegSet<2, [AX, CX, DX, BX], [AH, CH, DH, BH]>; The SubRegClassList is currently only used by ScheduleDAGSDNodesEmit.cpp to determine the register class of virtual registers defined by EXTRACT_SUBREG. If these badly classed virtual registers survive register coalescing, they cause unnecessary copies in the LowerSubregs pass. The attached patch replaces the GR8_ register class with two register classes: GR8_L and GR8_H, corresponding to the low and high halves of the GR16_ registers. The patch passes "make check". -------------- next part -------------- A non-text attachment was scrubbed... Name: x86-gr8h.patch Type: application/octet-stream Size: 3952 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090426/27cc7af8/attachment.obj -------------- next part -------------- From sanjiv.gupta at microchip.com Sun Apr 26 12:14:35 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Sun, 26 Apr 2009 17:14:35 -0000 Subject: [llvm-commits] [llvm] r70134 - in /llvm/trunk: docs/LangRef.html lib/VMCore/Type.cpp test/Assembler/getelementptr_struct.ll Message-ID: <200904261714.n3QHEZSs018745@zion.cs.uiuc.edu> Author: sgupta Date: Sun Apr 26 12:14:35 2009 New Revision: 70134 URL: http://llvm.org/viewvc/llvm-project?rev=70134&view=rev Log: Any size of integral indices are allowed in gep for indexing into sequential types. Also adding a test case to check the indices type allowed into struct. Added: llvm/trunk/test/Assembler/getelementptr_struct.ll Modified: llvm/trunk/docs/LangRef.html llvm/trunk/lib/VMCore/Type.cpp Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=70134&r1=70133&r2=70134&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Sun Apr 26 12:14:35 2009 @@ -3629,7 +3629,7 @@

    The type of each index argument depends on the type it is indexing into. When indexing into a (packed) structure, only i32 integer constants are allowed. When indexing into an array, pointer or vector, -only integers of 16, 32 or 64 bits are allowed (also non-constants). 16-bit +integers of any width are allowed (also non-constants). 16-bit values will be sign extended to 32-bits if required, and 32-bit values will be sign extended to 64-bits if required.

    Modified: llvm/trunk/lib/VMCore/Type.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=70134&r1=70133&r2=70134&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Type.cpp (original) +++ llvm/trunk/lib/VMCore/Type.cpp Sun Apr 26 12:14:35 2009 @@ -1410,9 +1410,8 @@ } bool SequentialType::indexValid(const Value *V) const { - if (const IntegerType *IT = dyn_cast(V->getType())) - return IT->getBitWidth() == 16 || IT->getBitWidth() == 32 || - IT->getBitWidth() == 64; + if (isa(V->getType())) + return true; return false; } Added: llvm/trunk/test/Assembler/getelementptr_struct.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/getelementptr_struct.ll?rev=70134&view=auto ============================================================================== --- llvm/trunk/test/Assembler/getelementptr_struct.ll (added) +++ llvm/trunk/test/Assembler/getelementptr_struct.ll Sun Apr 26 12:14:35 2009 @@ -0,0 +1,12 @@ +; RUN: not llvm-as < %s >/dev/null |& grep {invalid getelementptr indices} +; Test the case of a incorrect indices type into struct + +%RT = type { i8 , [10 x [20 x i32]], i8 } +%ST = type { i32, double, %RT } + +define i32* @foo(%ST* %s) { +entry: + %reg = getelementptr %ST* %s, i32 1, i64 2, i32 1, i32 5, i32 13 + ret i32* %reg +} + From isanbard at gmail.com Sun Apr 26 13:10:20 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 18:10:20 -0000 Subject: [llvm-commits] [llvm] r70138 - /llvm/trunk/include/llvm/ADT/PointerIntPair.h Message-ID: <200904261810.n3QIAKhb020458@zion.cs.uiuc.edu> Author: void Date: Sun Apr 26 13:10:20 2009 New Revision: 70138 URL: http://llvm.org/viewvc/llvm-project?rev=70138&view=rev Log: Suppress warnings about conversion shortening 64-bit to 32-bit. Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/PointerIntPair.h?rev=70138&r1=70137&r2=70138&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/PointerIntPair.h (original) +++ llvm/trunk/include/llvm/ADT/PointerIntPair.h Sun Apr 26 13:10:20 2009 @@ -42,16 +42,18 @@ intptr_t Value; enum { /// PointerBitMask - The bits that come from the pointer. - PointerBitMask = ~(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + PointerBitMask = + ~(unsigned)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + /// IntShift - The number of low bits that we reserve for other uses, and /// keep zero. - IntShift = PtrTraits::NumLowBitsAvailable-IntBits, + IntShift = (unsigned)PtrTraits::NumLowBitsAvailable-IntBits, /// IntMask - This is the unshifted mask for valid bits of the int type. - IntMask = ((intptr_t)1 << IntBits)-1, + IntMask = (unsigned)(((intptr_t)1 << IntBits)-1), // ShiftedIntMask - This is the bits for the integer shifted in place. - ShiftedIntMask = IntMask << IntShift + ShiftedIntMask = (unsigned)(IntMask << IntShift) }; public: PointerIntPair() : Value(0) {} From isanbard at gmail.com Sun Apr 26 13:12:38 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 18:12:38 -0000 Subject: [llvm-commits] [llvm] r70140 - /llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h Message-ID: <200904261812.n3QICcTc020566@zion.cs.uiuc.edu> Author: void Date: Sun Apr 26 13:12:38 2009 New Revision: 70140 URL: http://llvm.org/viewvc/llvm-project?rev=70140&view=rev Log: Suppress warnings about conversion shortening 64-bit to 32-bit. Modified: llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h Modified: llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h URL: http://llvm.org/viewvc/llvm-project/llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h?rev=70140&r1=70139&r2=70140&view=diff ============================================================================== --- llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h (original) +++ llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h Sun Apr 26 13:12:38 2009 @@ -42,16 +42,18 @@ intptr_t Value; enum { /// PointerBitMask - The bits that come from the pointer. - PointerBitMask = ~(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + PointerBitMask = + ~(unsigned)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + /// IntShift - The number of low bits that we reserve for other uses, and /// keep zero. - IntShift = PtrTraits::NumLowBitsAvailable-IntBits, + IntShift = (unsigned)PtrTraits::NumLowBitsAvailable-IntBits, /// IntMask - This is the unshifted mask for valid bits of the int type. - IntMask = ((intptr_t)1 << IntBits)-1, + IntMask = (unsigned)(((intptr_t)1 << IntBits)-1), // ShiftedIntMask - This is the bits for the integer shifted in place. - ShiftedIntMask = IntMask << IntShift + ShiftedIntMask = (unsigned)(IntMask << IntShift) }; public: PointerIntPair() : Value(0) {} From baldrick at free.fr Sun Apr 26 13:28:05 2009 From: baldrick at free.fr (Duncan Sands) Date: Sun, 26 Apr 2009 20:28:05 +0200 Subject: [llvm-commits] [llvm] r70134 - in /llvm/trunk: docs/LangRef.html lib/VMCore/Type.cpp test/Assembler/getelementptr_struct.ll In-Reply-To: <200904261714.n3QHEZSs018745@zion.cs.uiuc.edu> References: <200904261714.n3QHEZSs018745@zion.cs.uiuc.edu> Message-ID: <200904262028.06332.baldrick@free.fr> Hi Sanjiv, >

    The type of each index argument depends on the type it is indexing into. > When indexing into a (packed) structure, only i32 integer > constants are allowed. When indexing into an array, pointer or vector, > -only integers of 16, 32 or 64 bits are allowed (also non-constants). 16-bit > +integers of any width are allowed (also non-constants). 16-bit > values will be sign extended to 32-bits if required, and 32-bit values > will be sign extended to 64-bits if required.

    the bit about 16-bit values being extended to 32 bit etc sounds odd now. Ciao, Duncan. From clattner at apple.com Sun Apr 26 13:42:20 2009 From: clattner at apple.com (Chris Lattner) Date: Sun, 26 Apr 2009 11:42:20 -0700 Subject: [llvm-commits] [llvm] r70140 - /llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h In-Reply-To: <200904261812.n3QICcTc020566@zion.cs.uiuc.edu> References: <200904261812.n3QICcTc020566@zion.cs.uiuc.edu> Message-ID: <461F0595-8308-4353-BC03-640DC3F41B61@apple.com> On Apr 26, 2009, at 11:12 AM, Bill Wendling wrote: > Author: void > Date: Sun Apr 26 13:12:38 2009 > New Revision: 70140 > > URL: http://llvm.org/viewvc/llvm-project?rev=70140&view=rev > Log: > Suppress warnings about conversion shortening 64-bit to 32-bit. Bill, I don't think this is safe on 64-bit systems. PointerBitMask will be 32-bit not 64-bit. How about casting to uint64_t instead of unsigned? -Chris > > > Modified: > llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h > > Modified: llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/ > PointerIntPair.h > URL: http://llvm.org/viewvc/llvm-project/llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h?rev=70140&r1=70139&r2=70140&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/ > PointerIntPair.h (original) > +++ llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/ > PointerIntPair.h Sun Apr 26 13:12:38 2009 > @@ -42,16 +42,18 @@ > intptr_t Value; > enum { > /// PointerBitMask - The bits that come from the pointer. > - PointerBitMask = ~(((intptr_t)1 << > PtrTraits::NumLowBitsAvailable)-1), > + PointerBitMask = > + ~(unsigned)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), > + > /// IntShift - The number of low bits that we reserve for other > uses, and > /// keep zero. > - IntShift = PtrTraits::NumLowBitsAvailable-IntBits, > + IntShift = (unsigned)PtrTraits::NumLowBitsAvailable-IntBits, > > /// IntMask - This is the unshifted mask for valid bits of the > int type. > - IntMask = ((intptr_t)1 << IntBits)-1, > + IntMask = (unsigned)(((intptr_t)1 << IntBits)-1), > > // ShiftedIntMask - This is the bits for the integer shifted in > place. > - ShiftedIntMask = IntMask << IntShift > + ShiftedIntMask = (unsigned)(IntMask << IntShift) > }; > public: > PointerIntPair() : Value(0) {} > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From sabre at nondot.org Sun Apr 26 14:44:20 2009 From: sabre at nondot.org (Chris Lattner) Date: Sun, 26 Apr 2009 19:44:20 -0000 Subject: [llvm-commits] [llvm] r70147 - /llvm/trunk/include/llvm/ADT/PointerIntPair.h Message-ID: <200904261944.n3QJiKa1023907@zion.cs.uiuc.edu> Author: lattner Date: Sun Apr 26 14:44:20 2009 New Revision: 70147 URL: http://llvm.org/viewvc/llvm-project?rev=70147&view=rev Log: revert an incorrect patch. This causes crashes all over the place on a 64-bit build. Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/PointerIntPair.h?rev=70147&r1=70146&r2=70147&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/PointerIntPair.h (original) +++ llvm/trunk/include/llvm/ADT/PointerIntPair.h Sun Apr 26 14:44:20 2009 @@ -42,18 +42,16 @@ intptr_t Value; enum { /// PointerBitMask - The bits that come from the pointer. - PointerBitMask = - ~(unsigned)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), - + PointerBitMask = ~(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), /// IntShift - The number of low bits that we reserve for other uses, and /// keep zero. - IntShift = (unsigned)PtrTraits::NumLowBitsAvailable-IntBits, + IntShift = PtrTraits::NumLowBitsAvailable-IntBits, /// IntMask - This is the unshifted mask for valid bits of the int type. - IntMask = (unsigned)(((intptr_t)1 << IntBits)-1), + IntMask = ((intptr_t)1 << IntBits)-1, // ShiftedIntMask - This is the bits for the integer shifted in place. - ShiftedIntMask = (unsigned)(IntMask << IntShift) + ShiftedIntMask = IntMask << IntShift }; public: PointerIntPair() : Value(0) {} From isanbard at gmail.com Sun Apr 26 14:46:43 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 19:46:43 -0000 Subject: [llvm-commits] [llvm] r70148 - /llvm/trunk/include/llvm/ADT/PointerIntPair.h Message-ID: <200904261946.n3QJki69023983@zion.cs.uiuc.edu> Author: void Date: Sun Apr 26 14:46:41 2009 New Revision: 70148 URL: http://llvm.org/viewvc/llvm-project?rev=70148&view=rev Log: Use uint64_t instead of unsigned. Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/PointerIntPair.h?rev=70148&r1=70147&r2=70148&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/PointerIntPair.h (original) +++ llvm/trunk/include/llvm/ADT/PointerIntPair.h Sun Apr 26 14:46:41 2009 @@ -42,16 +42,18 @@ intptr_t Value; enum { /// PointerBitMask - The bits that come from the pointer. - PointerBitMask = ~(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + PointerBitMask = + ~(uint64_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + /// IntShift - The number of low bits that we reserve for other uses, and /// keep zero. - IntShift = PtrTraits::NumLowBitsAvailable-IntBits, + IntShift = (uint64_t)PtrTraits::NumLowBitsAvailable-IntBits, /// IntMask - This is the unshifted mask for valid bits of the int type. - IntMask = ((intptr_t)1 << IntBits)-1, + IntMask = (uint64_t)(((intptr_t)1 << IntBits)-1), // ShiftedIntMask - This is the bits for the integer shifted in place. - ShiftedIntMask = IntMask << IntShift + ShiftedIntMask = (uint64_t)(IntMask << IntShift) }; public: PointerIntPair() : Value(0) {} From isanbard at gmail.com Sun Apr 26 14:49:01 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 19:49:01 -0000 Subject: [llvm-commits] [llvm] r70150 - /llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h Message-ID: <200904261949.n3QJn16t024063@zion.cs.uiuc.edu> Author: void Date: Sun Apr 26 14:49:00 2009 New Revision: 70150 URL: http://llvm.org/viewvc/llvm-project?rev=70150&view=rev Log: Use uint64_t instead of unsigned. Modified: llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h Modified: llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h URL: http://llvm.org/viewvc/llvm-project/llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h?rev=70150&r1=70149&r2=70150&view=diff ============================================================================== --- llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h (original) +++ llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h Sun Apr 26 14:49:00 2009 @@ -43,17 +43,17 @@ enum { /// PointerBitMask - The bits that come from the pointer. PointerBitMask = - ~(unsigned)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + ~(uint64_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), /// IntShift - The number of low bits that we reserve for other uses, and /// keep zero. - IntShift = (unsigned)PtrTraits::NumLowBitsAvailable-IntBits, + IntShift = (uint64_t)PtrTraits::NumLowBitsAvailable-IntBits, /// IntMask - This is the unshifted mask for valid bits of the int type. - IntMask = (unsigned)(((intptr_t)1 << IntBits)-1), + IntMask = (uint64_t)(((intptr_t)1 << IntBits)-1), // ShiftedIntMask - This is the bits for the integer shifted in place. - ShiftedIntMask = (unsigned)(IntMask << IntShift) + ShiftedIntMask = (uint64_t)(IntMask << IntShift) }; public: PointerIntPair() : Value(0) {} From clattner at apple.com Sun Apr 26 14:50:25 2009 From: clattner at apple.com (Chris Lattner) Date: Sun, 26 Apr 2009 12:50:25 -0700 Subject: [llvm-commits] [llvm] r70148 - /llvm/trunk/include/llvm/ADT/PointerIntPair.h In-Reply-To: <200904261946.n3QJki69023983@zion.cs.uiuc.edu> References: <200904261946.n3QJki69023983@zion.cs.uiuc.edu> Message-ID: On Apr 26, 2009, at 12:46 PM, Bill Wendling wrote: > Author: void > Date: Sun Apr 26 14:46:41 2009 > New Revision: 70148 > > URL: http://llvm.org/viewvc/llvm-project?rev=70148&view=rev > Log: > Use uint64_t instead of unsigned. This isn't right for 32-bit hosts! -Chris > > > Modified: > llvm/trunk/include/llvm/ADT/PointerIntPair.h > > Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/PointerIntPair.h?rev=70148&r1=70147&r2=70148&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/include/llvm/ADT/PointerIntPair.h (original) > +++ llvm/trunk/include/llvm/ADT/PointerIntPair.h Sun Apr 26 14:46:41 > 2009 > @@ -42,16 +42,18 @@ > intptr_t Value; > enum { > /// PointerBitMask - The bits that come from the pointer. > - PointerBitMask = ~(((intptr_t)1 << > PtrTraits::NumLowBitsAvailable)-1), > + PointerBitMask = > + ~(uint64_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), > + > /// IntShift - The number of low bits that we reserve for other > uses, and > /// keep zero. > - IntShift = PtrTraits::NumLowBitsAvailable-IntBits, > + IntShift = (uint64_t)PtrTraits::NumLowBitsAvailable-IntBits, > > /// IntMask - This is the unshifted mask for valid bits of the > int type. > - IntMask = ((intptr_t)1 << IntBits)-1, > + IntMask = (uint64_t)(((intptr_t)1 << IntBits)-1), > > // ShiftedIntMask - This is the bits for the integer shifted in > place. > - ShiftedIntMask = IntMask << IntShift > + ShiftedIntMask = (uint64_t)(IntMask << IntShift) > }; > public: > PointerIntPair() : Value(0) {} > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From isanbard at gmail.com Sun Apr 26 14:57:19 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 12:57:19 -0700 Subject: [llvm-commits] [llvm] r70148 - /llvm/trunk/include/llvm/ADT/PointerIntPair.h In-Reply-To: References: <200904261946.n3QJki69023983@zion.cs.uiuc.edu> Message-ID: On Apr 26, 2009, at 12:50 PM, Chris Lattner wrote: > On Apr 26, 2009, at 12:46 PM, Bill Wendling wrote: > >> Author: void >> Date: Sun Apr 26 14:46:41 2009 >> New Revision: 70148 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=70148&view=rev >> Log: >> Use uint64_t instead of unsigned. > > This isn't right for 32-bit hosts! > Well, it was your suggestion. :-) What do you suggest now? If you use - Wshorten-64-to-32 when compiling with -m64, this enum emits warnings. -bw From clattner at apple.com Sun Apr 26 14:58:31 2009 From: clattner at apple.com (Chris Lattner) Date: Sun, 26 Apr 2009 12:58:31 -0700 Subject: [llvm-commits] [llvm] r70148 - /llvm/trunk/include/llvm/ADT/PointerIntPair.h In-Reply-To: References: <200904261946.n3QJki69023983@zion.cs.uiuc.edu> Message-ID: On Apr 26, 2009, at 12:57 PM, Bill Wendling wrote: > On Apr 26, 2009, at 12:50 PM, Chris Lattner wrote: > >> On Apr 26, 2009, at 12:46 PM, Bill Wendling wrote: >> >>> Author: void >>> Date: Sun Apr 26 14:46:41 2009 >>> New Revision: 70148 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=70148&view=rev >>> Log: >>> Use uint64_t instead of unsigned. >> >> This isn't right for 32-bit hosts! >> > Well, it was your suggestion. :-) What do you suggest now? If you > use - > Wshorten-64-to-32 when compiling with -m64, this enum emits warnings. intptr_t or uintptr_t. -Chris From isanbard at gmail.com Sun Apr 26 15:12:38 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 20:12:38 -0000 Subject: [llvm-commits] [llvm] r70151 - /llvm/trunk/include/llvm/ADT/PointerIntPair.h Message-ID: <200904262012.n3QKCcxp024911@zion.cs.uiuc.edu> Author: void Date: Sun Apr 26 15:12:38 2009 New Revision: 70151 URL: http://llvm.org/viewvc/llvm-project?rev=70151&view=rev Log: I cast, therefore I think I know what I'm doing. Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/PointerIntPair.h?rev=70151&r1=70150&r2=70151&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/PointerIntPair.h (original) +++ llvm/trunk/include/llvm/ADT/PointerIntPair.h Sun Apr 26 15:12:38 2009 @@ -43,17 +43,17 @@ enum { /// PointerBitMask - The bits that come from the pointer. PointerBitMask = - ~(uint64_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), /// IntShift - The number of low bits that we reserve for other uses, and /// keep zero. - IntShift = (uint64_t)PtrTraits::NumLowBitsAvailable-IntBits, + IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable-IntBits, /// IntMask - This is the unshifted mask for valid bits of the int type. - IntMask = (uint64_t)(((intptr_t)1 << IntBits)-1), + IntMask = (uintptr_t)(((intptr_t)1 << IntBits)-1), // ShiftedIntMask - This is the bits for the integer shifted in place. - ShiftedIntMask = (uint64_t)(IntMask << IntShift) + ShiftedIntMask = (uintptr_t)(IntMask << IntShift) }; public: PointerIntPair() : Value(0) {} From isanbard at gmail.com Sun Apr 26 15:13:44 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 20:13:44 -0000 Subject: [llvm-commits] [llvm] r70153 - /llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h Message-ID: <200904262013.n3QKDiQN024963@zion.cs.uiuc.edu> Author: void Date: Sun Apr 26 15:13:44 2009 New Revision: 70153 URL: http://llvm.org/viewvc/llvm-project?rev=70153&view=rev Log: Avoid warnings. Modified: llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h Modified: llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h URL: http://llvm.org/viewvc/llvm-project/llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h?rev=70153&r1=70152&r2=70153&view=diff ============================================================================== --- llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h (original) +++ llvm/tags/Apple/llvmCore-2107.1/include/llvm/ADT/PointerIntPair.h Sun Apr 26 15:13:44 2009 @@ -43,17 +43,17 @@ enum { /// PointerBitMask - The bits that come from the pointer. PointerBitMask = - ~(uint64_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), /// IntShift - The number of low bits that we reserve for other uses, and /// keep zero. - IntShift = (uint64_t)PtrTraits::NumLowBitsAvailable-IntBits, + IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable-IntBits, /// IntMask - This is the unshifted mask for valid bits of the int type. - IntMask = (uint64_t)(((intptr_t)1 << IntBits)-1), + IntMask = (uintptr_t)(((intptr_t)1 << IntBits)-1), // ShiftedIntMask - This is the bits for the integer shifted in place. - ShiftedIntMask = (uint64_t)(IntMask << IntShift) + ShiftedIntMask = (uintptr_t)(IntMask << IntShift) }; public: PointerIntPair() : Value(0) {} From clattner at apple.com Sun Apr 26 15:18:38 2009 From: clattner at apple.com (Chris Lattner) Date: Sun, 26 Apr 2009 13:18:38 -0700 Subject: [llvm-commits] [llvm] r70151 - /llvm/trunk/include/llvm/ADT/PointerIntPair.h In-Reply-To: <200904262012.n3QKCcxp024911@zion.cs.uiuc.edu> References: <200904262012.n3QKCcxp024911@zion.cs.uiuc.edu> Message-ID: <9C30C558-11A7-4C3B-8BF5-11B2DA7E1B2A@apple.com> On Apr 26, 2009, at 1:12 PM, Bill Wendling wrote: > Author: void > Date: Sun Apr 26 15:12:38 2009 > New Revision: 70151 > > URL: http://llvm.org/viewvc/llvm-project?rev=70151&view=rev > Log: > I cast, therefore I think I know what I'm doing. Thanks Bill :) -Chris From isanbard at gmail.com Sun Apr 26 15:42:56 2009 From: isanbard at gmail.com (Bill Wendling) Date: Sun, 26 Apr 2009 13:42:56 -0700 Subject: [llvm-commits] [llvm] r70151 - /llvm/trunk/include/llvm/ADT/PointerIntPair.h In-Reply-To: <9C30C558-11A7-4C3B-8BF5-11B2DA7E1B2A@apple.com> References: <200904262012.n3QKCcxp024911@zion.cs.uiuc.edu> <9C30C558-11A7-4C3B-8BF5-11B2DA7E1B2A@apple.com> Message-ID: <2D9435A8-85C4-42A4-B300-66EC546CB551@gmail.com> On Apr 26, 2009, at 1:18 PM, Chris Lattner wrote: > On Apr 26, 2009, at 1:12 PM, Bill Wendling wrote: > >> Author: void >> Date: Sun Apr 26 15:12:38 2009 >> New Revision: 70151 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=70151&view=rev >> Log: >> I cast, therefore I think I know what I'm doing. > > Thanks Bill :) > Sure thing. :-) -bw From sabre at nondot.org Sun Apr 26 15:59:03 2009 From: sabre at nondot.org (Chris Lattner) Date: Sun, 26 Apr 2009 20:59:03 -0000 Subject: [llvm-commits] [llvm] r70157 - in /llvm/trunk: include/llvm/Bitcode/BitstreamReader.h include/llvm/Bitcode/Deserialize.h lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Reader/BitcodeReader.h lib/Bitcode/Reader/Deserialize.cpp tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Message-ID: <200904262059.n3QKx3K0026374@zion.cs.uiuc.edu> Author: lattner Date: Sun Apr 26 15:59:02 2009 New Revision: 70157 URL: http://llvm.org/viewvc/llvm-project?rev=70157&view=rev Log: Make a major API change to BitstreamReader: split all the reading state out of the BitstreamReader class into a BitstreamCursor class. Doing this allows the client to have multiple cursors into the same file, each with potentially different live block stacks and abbreviation records. Modified: llvm/trunk/include/llvm/Bitcode/BitstreamReader.h llvm/trunk/include/llvm/Bitcode/Deserialize.h llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Modified: llvm/trunk/include/llvm/Bitcode/BitstreamReader.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitstreamReader.h?rev=70157&r1=70156&r2=70157&view=diff ============================================================================== --- llvm/trunk/include/llvm/Bitcode/BitstreamReader.h (original) +++ llvm/trunk/include/llvm/Bitcode/BitstreamReader.h Sun Apr 26 15:59:02 2009 @@ -24,72 +24,144 @@ class Deserializer; class BitstreamReader { - const unsigned char *NextChar; - const unsigned char *LastChar; - friend class Deserializer; +public: + /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. + /// These describe abbreviations that all blocks of the specified ID inherit. + struct BlockInfo { + unsigned BlockID; + std::vector Abbrevs; + }; +private: + /// FirstChar/LastChar - This remembers the first and last bytes of the + /// stream. + const unsigned char *FirstChar, *LastChar; + + std::vector BlockInfoRecords; + +public: + BitstreamReader() : FirstChar(0), LastChar(0) { + } + + BitstreamReader(const unsigned char *Start, const unsigned char *End) { + init(Start, End); + } + + void init(const unsigned char *Start, const unsigned char *End) { + FirstChar = Start; + LastChar = End; + assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); + } + + ~BitstreamReader() { + // Free the BlockInfoRecords. + while (!BlockInfoRecords.empty()) { + BlockInfo &Info = BlockInfoRecords.back(); + // Free blockinfo abbrev info. + for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); + i != e; ++i) + Info.Abbrevs[i]->dropRef(); + BlockInfoRecords.pop_back(); + } + } + + const unsigned char *getFirstChar() const { return FirstChar; } + const unsigned char *getLastChar() const { return LastChar; } + + //===--------------------------------------------------------------------===// + // Block Manipulation + //===--------------------------------------------------------------------===// + + /// getBlockInfo - If there is block info for the specified ID, return it, + /// otherwise return null. + BlockInfo *getBlockInfo(unsigned BlockID) { + // Common case, the most recent entry matches BlockID. + if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) + return &BlockInfoRecords.back(); + + for (unsigned i = 0, e = static_cast(BlockInfoRecords.size()); + i != e; ++i) + if (BlockInfoRecords[i].BlockID == BlockID) + return &BlockInfoRecords[i]; + return 0; + } + BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { + if (BlockInfo *BI = getBlockInfo(BlockID)) + return *BI; + + // Otherwise, add a new record. + BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.back().BlockID = BlockID; + return BlockInfoRecords.back(); + } + +}; + +class BitstreamCursor { + friend class Deserializer; + BitstreamReader *BitStream; + const unsigned char *NextChar; + /// CurWord - This is the current data we have pulled from the stream but have /// not returned to the client. uint32_t CurWord; - + /// BitsInCurWord - This is the number of bits in CurWord that are valid. This /// is always from [0...31] inclusive. unsigned BitsInCurWord; - + // CurCodeSize - This is the declared size of code values used for the current // block, in bits. unsigned CurCodeSize; - + /// CurAbbrevs - Abbrevs installed at in this block. std::vector CurAbbrevs; - + struct Block { unsigned PrevCodeSize; std::vector PrevAbbrevs; explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} }; - + /// BlockScope - This tracks the codesize of parent blocks. SmallVector BlockScope; - - /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. - /// These describe abbreviations that all blocks of the specified ID inherit. - struct BlockInfo { - unsigned BlockID; - std::vector Abbrevs; - }; - std::vector BlockInfoRecords; - - /// FirstChar - This remembers the first byte of the stream. - const unsigned char *FirstChar; + + BitstreamCursor(const BitstreamCursor&); // NOT YET IMPLEMENTED. + void operator=(const BitstreamCursor&); // NOT YET IMPLEMENTED. public: - BitstreamReader() { - NextChar = FirstChar = LastChar = 0; + BitstreamCursor() : BitStream(0), NextChar(0) { + } + explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) { + NextChar = R.getFirstChar(); + assert(NextChar && "Bitstream not initialized yet"); CurWord = 0; BitsInCurWord = 0; - CurCodeSize = 0; - } - - BitstreamReader(const unsigned char *Start, const unsigned char *End) { - init(Start, End); + CurCodeSize = 2; } - - void init(const unsigned char *Start, const unsigned char *End) { - NextChar = FirstChar = Start; - LastChar = End; - assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); + + void init(BitstreamReader &R) { + freeState(); + + BitStream = &R; + NextChar = R.getFirstChar(); + assert(NextChar && "Bitstream not initialized yet"); CurWord = 0; BitsInCurWord = 0; CurCodeSize = 2; } - - ~BitstreamReader() { - // Abbrevs could still exist if the stream was broken. If so, don't leak - // them. + + ~BitstreamCursor() { + freeState(); + } + + void freeState() { + // Free all the Abbrevs. for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); i != e; ++i) CurAbbrevs[i]->dropRef(); - + CurAbbrevs.clear(); + + // Free all the Abbrevs in the block scope. for (unsigned S = 0, e = static_cast(BlockScope.size()); S != e; ++S) { std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; @@ -97,47 +169,41 @@ i != e; ++i) Abbrevs[i]->dropRef(); } - - // Free the BlockInfoRecords. - while (!BlockInfoRecords.empty()) { - BlockInfo &Info = BlockInfoRecords.back(); - // Free blockinfo abbrev info. - for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); - i != e; ++i) - Info.Abbrevs[i]->dropRef(); - BlockInfoRecords.pop_back(); - } + BlockScope.clear(); } - + + /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #. + unsigned GetAbbrevIDWidth() const { return CurCodeSize; } + bool AtEndOfStream() const { - return NextChar == LastChar && BitsInCurWord == 0; + return NextChar == BitStream->getLastChar() && BitsInCurWord == 0; } - + /// GetCurrentBitNo - Return the bit # of the bit we are reading. uint64_t GetCurrentBitNo() const { - return (NextChar-FirstChar)*CHAR_BIT - BitsInCurWord; + return (NextChar-BitStream->getFirstChar())*CHAR_BIT - BitsInCurWord; } - + + /// JumpToBit - Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3; uintptr_t WordBitNo = uintptr_t(BitNo) & 31; - assert(ByteNo <= (uintptr_t)(LastChar-FirstChar) && "Invalid location"); - + assert(ByteNo <= (uintptr_t)(BitStream->getLastChar()- + BitStream->getFirstChar()) && + "Invalid location"); + // Move the cursor to the right word. - NextChar = FirstChar+ByteNo; + NextChar = BitStream->getFirstChar()+ByteNo; BitsInCurWord = 0; CurWord = 0; - + // Skip over any bits that are already consumed. - if (WordBitNo) { + if (WordBitNo) Read(static_cast(WordBitNo)); - } } - - /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #. - unsigned GetAbbrevIDWidth() const { return CurCodeSize; } - + + uint32_t Read(unsigned NumBits) { // If the field is fully contained by CurWord, return it quickly. if (BitsInCurWord >= NumBits) { @@ -148,7 +214,7 @@ } // If we run out of data, stop at the end of the stream. - if (NextChar == LastChar) { + if (NextChar == BitStream->getLastChar()) { CurWord = 0; BitsInCurWord = 0; return 0; @@ -224,31 +290,10 @@ CurWord = 0; } - unsigned ReadCode() { return Read(CurCodeSize); } - //===--------------------------------------------------------------------===// - // Block Manipulation - //===--------------------------------------------------------------------===// - -private: - /// getBlockInfo - If there is block info for the specified ID, return it, - /// otherwise return null. - BlockInfo *getBlockInfo(unsigned BlockID) { - // Common case, the most recent entry matches BlockID. - if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) - return &BlockInfoRecords.back(); - - for (unsigned i = 0, e = static_cast(BlockInfoRecords.size()); - i != e; ++i) - if (BlockInfoRecords[i].BlockID == BlockID) - return &BlockInfoRecords[i]; - return 0; - } -public: - // Block header: // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] @@ -271,7 +316,7 @@ // Check that the block wasn't partially defined, and that the offset isn't // bogus. - if (AtEndOfStream() || NextChar+NumWords*4 > LastChar) + if (AtEndOfStream() || NextChar+NumWords*4 > BitStream->getLastChar()) return true; NextChar += NumWords*4; @@ -286,7 +331,7 @@ BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); // Add the abbrevs specific to this block to the CurAbbrevs list. - if (BlockInfo *Info = getBlockInfo(BlockID)) { + if (BitstreamReader::BlockInfo *Info = BitStream->getBlockInfo(BlockID)) { for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); i != e; ++i) { CurAbbrevs.push_back(Info->Abbrevs[i]); @@ -301,7 +346,8 @@ if (NumWordsP) *NumWordsP = NumWords; // Validate that this block is sane. - if (CurCodeSize == 0 || AtEndOfStream() || NextChar+NumWords*4 > LastChar) + if (CurCodeSize == 0 || AtEndOfStream() || + NextChar+NumWords*4 > BitStream->getLastChar()) return true; return false; @@ -331,7 +377,7 @@ BlockScope.pop_back(); } - //===--------------------------------------------------------------------===// + //===--------------------------------------------------------------------===// // Record Processing //===--------------------------------------------------------------------===// @@ -407,9 +453,9 @@ // If this would read off the end of the bitcode file, just set the // record to empty and return. - if (NewEnd > LastChar) { + if (NewEnd > BitStream->getLastChar()) { Vals.append(NumElts, 0); - NextChar = LastChar; + NextChar = BitStream->getLastChar(); break; } @@ -462,29 +508,14 @@ } CurAbbrevs.push_back(Abbv); } - - //===--------------------------------------------------------------------===// - // BlockInfo Block Reading - //===--------------------------------------------------------------------===// - -private: - BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { - if (BlockInfo *BI = getBlockInfo(BlockID)) - return *BI; - - // Otherwise, add a new record. - BlockInfoRecords.push_back(BlockInfo()); - BlockInfoRecords.back().BlockID = BlockID; - return BlockInfoRecords.back(); - } - + public: bool ReadBlockInfoBlock() { if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; SmallVector Record; - BlockInfo *CurBlockInfo = 0; + BitstreamReader::BlockInfo *CurBlockInfo = 0; // Read all the records for this module. while (1) { @@ -516,13 +547,13 @@ default: break; // Default behavior, ignore unknown content. case bitc::BLOCKINFO_CODE_SETBID: if (Record.size() < 1) return true; - CurBlockInfo = &getOrCreateBlockInfo((unsigned)Record[0]); + CurBlockInfo = &BitStream->getOrCreateBlockInfo((unsigned)Record[0]); break; } } } }; - + } // End llvm namespace #endif Modified: llvm/trunk/include/llvm/Bitcode/Deserialize.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/Deserialize.h?rev=70157&r1=70156&r2=70157&view=diff ============================================================================== --- llvm/trunk/include/llvm/Bitcode/Deserialize.h (original) +++ llvm/trunk/include/llvm/Bitcode/Deserialize.h Sun Apr 26 15:59:02 2009 @@ -116,7 +116,7 @@ //===----------------------------------------------------------===// private: - BitstreamReader& Stream; + BitstreamCursor Stream; SmallVector Record; unsigned RecIdx; BumpPtrAllocator Allocator; @@ -482,7 +482,7 @@ unsigned getRecordCode(); - BitstreamReader& getStream() { return Stream; } + BitstreamCursor &getStream() { return Stream; } private: bool AdvanceStream(); Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=70157&r1=70156&r2=70157&view=diff ============================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original) +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Sun Apr 26 15:59:02 2009 @@ -1346,7 +1346,8 @@ if (SkipBitcodeWrapperHeader(BufPtr, BufEnd)) return Error("Invalid bitcode wrapper header"); - Stream.init(BufPtr, BufEnd); + StreamFile.init(BufPtr, BufEnd); + Stream.init(StreamFile); // Sniff for the signature. if (Stream.Read(8) != 'B' || Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h?rev=70157&r1=70156&r2=70157&view=diff ============================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h (original) +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h Sun Apr 26 15:59:02 2009 @@ -86,7 +86,8 @@ class BitcodeReader : public ModuleProvider { MemoryBuffer *Buffer; - BitstreamReader Stream; + BitstreamReader StreamFile; + BitstreamCursor Stream; const char *ErrorString; Modified: llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp?rev=70157&r1=70156&r2=70157&view=diff ============================================================================== --- llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp (original) +++ llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp Sun Apr 26 15:59:02 2009 @@ -22,7 +22,7 @@ Deserializer::Deserializer(BitstreamReader& stream) : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) { - StreamStart = Stream.GetCurrentBitNo(); + StreamStart = Stream.GetCurrentBitNo(); } Deserializer::~Deserializer() { Modified: llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp?rev=70157&r1=70156&r2=70157&view=diff ============================================================================== --- llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp (original) +++ llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Sun Apr 26 15:59:02 2009 @@ -262,7 +262,7 @@ } /// ParseBlock - Read a block, updating statistics, etc. -static bool ParseBlock(BitstreamReader &Stream, unsigned IndentLevel) { +static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { std::string Indent(IndentLevel*2, ' '); uint64_t BlockBitStart = Stream.GetCurrentBitNo(); unsigned BlockID = Stream.ReadSubBlockID(); @@ -420,8 +420,8 @@ if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr)) return Error("Invalid bitcode wrapper header"); - BitstreamReader Stream(BufPtr, EndBufPtr); - + BitstreamReader StreamFile(BufPtr, EndBufPtr); + BitstreamCursor Stream(StreamFile); // Read the stream signature. char Signature[6]; From sabre at nondot.org Sun Apr 26 16:07:02 2009 From: sabre at nondot.org (Chris Lattner) Date: Sun, 26 Apr 2009 21:07:02 -0000 Subject: [llvm-commits] [llvm] r70159 - /llvm/trunk/include/llvm/Bitcode/BitstreamReader.h Message-ID: <200904262107.n3QL725M026721@zion.cs.uiuc.edu> Author: lattner Date: Sun Apr 26 16:07:02 2009 New Revision: 70159 URL: http://llvm.org/viewvc/llvm-project?rev=70159&view=rev Log: make BitstreamCursor's copyable and assignable. Modified: llvm/trunk/include/llvm/Bitcode/BitstreamReader.h Modified: llvm/trunk/include/llvm/Bitcode/BitstreamReader.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitstreamReader.h?rev=70159&r1=70158&r2=70159&view=diff ============================================================================== --- llvm/trunk/include/llvm/Bitcode/BitstreamReader.h (original) +++ llvm/trunk/include/llvm/Bitcode/BitstreamReader.h Sun Apr 26 16:07:02 2009 @@ -71,6 +71,11 @@ // Block Manipulation //===--------------------------------------------------------------------===// + /// hasBlockInfoRecords - Return true if we've already read and processed the + /// block info block for this Bitstream. We only process it for the first + /// cursor that walks over it. + bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } + /// getBlockInfo - If there is block info for the specified ID, return it, /// otherwise return null. BlockInfo *getBlockInfo(unsigned BlockID) { @@ -126,11 +131,13 @@ /// BlockScope - This tracks the codesize of parent blocks. SmallVector BlockScope; - BitstreamCursor(const BitstreamCursor&); // NOT YET IMPLEMENTED. - void operator=(const BitstreamCursor&); // NOT YET IMPLEMENTED. public: BitstreamCursor() : BitStream(0), NextChar(0) { } + BitstreamCursor(const BitstreamCursor &RHS) : BitStream(0), NextChar(0) { + operator=(RHS); + } + explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) { NextChar = R.getFirstChar(); assert(NextChar && "Bitstream not initialized yet"); @@ -154,6 +161,31 @@ freeState(); } + void operator=(const BitstreamCursor &RHS) { + freeState(); + + BitStream = RHS.BitStream; + NextChar = RHS.NextChar; + CurWord = RHS.CurWord; + BitsInCurWord = RHS.BitsInCurWord; + CurCodeSize = RHS.CurCodeSize; + + // Copy abbreviations, and bump ref counts. + CurAbbrevs = RHS.CurAbbrevs; + for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); + i != e; ++i) + CurAbbrevs[i]->addRef(); + + // Copy block scope and bump ref counts. + for (unsigned S = 0, e = static_cast(BlockScope.size()); + S != e; ++S) { + std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; + for (unsigned i = 0, e = static_cast(Abbrevs.size()); + i != e; ++i) + Abbrevs[i]->addRef(); + } + } + void freeState() { // Free all the Abbrevs. for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); @@ -512,6 +544,10 @@ public: bool ReadBlockInfoBlock() { + // If this is the second stream to get to the block info block, skip it. + if (BitStream->hasBlockInfoRecords()) + return SkipBlock(); + if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; SmallVector Record; From sabre at nondot.org Sun Apr 26 17:21:58 2009 From: sabre at nondot.org (Chris Lattner) Date: Sun, 26 Apr 2009 22:21:58 -0000 Subject: [llvm-commits] [llvm] r70165 - in /llvm/trunk: docs/BitCodeFormat.html include/llvm/Bitcode/BitCodes.h include/llvm/Bitcode/BitstreamReader.h tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Message-ID: <200904262221.n3QMLx0a028970@zion.cs.uiuc.edu> Author: lattner Date: Sun Apr 26 17:21:57 2009 New Revision: 70165 URL: http://llvm.org/viewvc/llvm-project?rev=70165&view=rev Log: Add two new record types to the blockinfo block: BLOCKNAME and SETRECORDNAME. This allows a bitcode file to be self describing with pretty names for records and blocks in addition to numbers. This enhances llvm-bcanalyzer to use this to print prettily. Modified: llvm/trunk/docs/BitCodeFormat.html llvm/trunk/include/llvm/Bitcode/BitCodes.h llvm/trunk/include/llvm/Bitcode/BitstreamReader.h llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Modified: llvm/trunk/docs/BitCodeFormat.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/BitCodeFormat.html?rev=70165&r1=70164&r2=70165&view=diff ============================================================================== --- llvm/trunk/docs/BitCodeFormat.html (original) +++ llvm/trunk/docs/BitCodeFormat.html Sun Apr 26 17:21:57 2009 @@ -563,6 +563,8 @@
     [SETBID (#1), blockid]
     [DEFINE_ABBREV, ...]
    +[BLOCKNAME, ...name...]
    +[SETRECORDNAME, RecordID, ...name...]
     
    @@ -582,6 +584,15 @@ in DEFINE_ABBREV.

    +

    The BLOCKNAME can optionally occur in this block. The elements of +the record are the bytes for the string name of the block. llvm-bcanalyzer uses +this to dump out bitcode files symbolically.

    + +

    The SETRECORDNAME record can optionally occur in this block. The +first entry is a record ID number and the rest of the elements of the record are +the bytes for the string name of the record. llvm-bcanalyzer uses +this to dump out bitcode files symbolically.

    +

    Note that although the data in BLOCKINFO blocks is described as "metadata," the abbreviations they contain are essential for parsing records Modified: llvm/trunk/include/llvm/Bitcode/BitCodes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitCodes.h?rev=70165&r1=70164&r2=70165&view=diff ============================================================================== --- llvm/trunk/include/llvm/Bitcode/BitCodes.h (original) +++ llvm/trunk/include/llvm/Bitcode/BitCodes.h Sun Apr 26 17:21:57 2009 @@ -66,10 +66,12 @@ /// BlockInfoCodes - The blockinfo block contains metadata about user-defined /// blocks. enum BlockInfoCodes { - BLOCKINFO_CODE_SETBID = 1 // SETBID: [blockid#] // DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd // block, instead of the BlockInfo block. - // BLOCKNAME: give string name to block, if desired. + + BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#] + BLOCKINFO_CODE_BLOCKNAME = 2, // BLOCKNAME: [name] + BLOCKINFO_CODE_SETRECORDNAME = 3 // BLOCKINFO_CODE_SETRECORDNAME: [id, name] }; } // End bitc namespace Modified: llvm/trunk/include/llvm/Bitcode/BitstreamReader.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitstreamReader.h?rev=70165&r1=70164&r2=70165&view=diff ============================================================================== --- llvm/trunk/include/llvm/Bitcode/BitstreamReader.h (original) +++ llvm/trunk/include/llvm/Bitcode/BitstreamReader.h Sun Apr 26 17:21:57 2009 @@ -30,6 +30,9 @@ struct BlockInfo { unsigned BlockID; std::vector Abbrevs; + std::string Name; + + std::vector > RecordNames; }; private: /// FirstChar/LastChar - This remembers the first and last bytes of the @@ -78,7 +81,7 @@ /// getBlockInfo - If there is block info for the specified ID, return it, /// otherwise return null. - BlockInfo *getBlockInfo(unsigned BlockID) { + const BlockInfo *getBlockInfo(unsigned BlockID) const { // Common case, the most recent entry matches BlockID. if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) return &BlockInfoRecords.back(); @@ -91,8 +94,8 @@ } BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { - if (BlockInfo *BI = getBlockInfo(BlockID)) - return *BI; + if (const BlockInfo *BI = getBlockInfo(BlockID)) + return *const_cast(BI); // Otherwise, add a new record. BlockInfoRecords.push_back(BlockInfo()); @@ -216,6 +219,13 @@ return (NextChar-BitStream->getFirstChar())*CHAR_BIT - BitsInCurWord; } + BitstreamReader *getBitStreamReader() { + return BitStream; + } + const BitstreamReader *getBitStreamReader() const { + return BitStream; + } + /// JumpToBit - Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { @@ -363,7 +373,8 @@ BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); // Add the abbrevs specific to this block to the CurAbbrevs list. - if (BitstreamReader::BlockInfo *Info = BitStream->getBlockInfo(BlockID)) { + if (const BitstreamReader::BlockInfo *Info = + BitStream->getBlockInfo(BlockID)) { for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); i != e; ++i) { CurAbbrevs.push_back(Info->Abbrevs[i]); @@ -585,6 +596,23 @@ if (Record.size() < 1) return true; CurBlockInfo = &BitStream->getOrCreateBlockInfo((unsigned)Record[0]); break; + case bitc::BLOCKINFO_CODE_BLOCKNAME: { + if (!CurBlockInfo) return true; + std::string Name; + for (unsigned i = 0, e = Record.size(); i != e; ++i) + Name += (char)Record[i]; + CurBlockInfo->Name = Name; + break; + } + case bitc::BLOCKINFO_CODE_SETRECORDNAME: { + if (!CurBlockInfo) return true; + std::string Name; + for (unsigned i = 1, e = Record.size(); i != e; ++i) + Name += (char)Record[i]; + CurBlockInfo->RecordNames.push_back(std::make_pair((unsigned)Record[0], + Name)); + break; + } } } } Modified: llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp?rev=70165&r1=70164&r2=70165&view=diff ============================================================================== --- llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp (original) +++ llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Sun Apr 26 17:21:57 2009 @@ -72,7 +72,8 @@ /// GetBlockName - Return a symbolic block name if known, otherwise return /// null. -static const char *GetBlockName(unsigned BlockID) { +static const char *GetBlockName(unsigned BlockID, + const BitstreamReader &StreamFile) { // Standard blocks for all bitcode files. if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { if (BlockID == bitc::BLOCKINFO_BLOCK_ID) @@ -80,6 +81,14 @@ return 0; } + // Check to see if we have a blockinfo record for this block, with a name. + if (const BitstreamReader::BlockInfo *Info = + StreamFile.getBlockInfo(BlockID)) { + if (!Info->Name.empty()) + return Info->Name.c_str(); + } + + if (CurStreamType != LLVMIRBitstream) return 0; switch (BlockID) { @@ -96,18 +105,30 @@ /// GetCodeName - Return a symbolic code name if known, otherwise return /// null. -static const char *GetCodeName(unsigned CodeID, unsigned BlockID) { +static const char *GetCodeName(unsigned CodeID, unsigned BlockID, + const BitstreamReader &StreamFile) { // Standard blocks for all bitcode files. if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { switch (CodeID) { default: return 0; - case bitc::MODULE_CODE_VERSION: return "VERSION"; + case bitc::BLOCKINFO_CODE_SETBID: return "SETBID"; + case bitc::BLOCKINFO_CODE_BLOCKNAME: return "BLOCKNAME"; + case bitc::BLOCKINFO_CODE_SETRECORDNAME: return "SETRECORDNAME"; } } return 0; } + // Check to see if we have a blockinfo record for this record, with a name. + if (const BitstreamReader::BlockInfo *Info = + StreamFile.getBlockInfo(BlockID)) { + for (unsigned i = 0, e = Info->RecordNames.size(); i != e; ++i) + if (Info->RecordNames[i].first == CodeID) + return Info->RecordNames[i].second.c_str(); + } + + if (CurStreamType != LLVMIRBitstream) return 0; switch (BlockID) { @@ -289,7 +310,7 @@ const char *BlockName = 0; if (Dump) { std::cerr << Indent << "<"; - if ((BlockName = GetBlockName(BlockID))) + if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader()))) std::cerr << BlockName; else std::cerr << "UnknownBlock" << BlockID; @@ -358,11 +379,13 @@ if (Dump) { std::cerr << Indent << " <"; - if (const char *CodeName = GetCodeName(Code, BlockID)) + if (const char *CodeName = + GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) std::cerr << CodeName; else std::cerr << "UnknownCode" << Code; - if (NonSymbolic && GetCodeName(Code, BlockID)) + if (NonSymbolic && + GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) std::cerr << " codeid=" << Code; if (AbbrevID != bitc::UNABBREV_RECORD) std::cerr << " abbrevid=" << AbbrevID; @@ -474,7 +497,7 @@ for (std::map::iterator I = BlockIDStats.begin(), E = BlockIDStats.end(); I != E; ++I) { std::cerr << " Block ID #" << I->first; - if (const char *BlockName = GetBlockName(I->first)) + if (const char *BlockName = GetBlockName(I->first, StreamFile)) std::cerr << " (" << BlockName << ")"; std::cerr << ":\n"; @@ -517,7 +540,8 @@ std::cerr << "\tCode Histogram:\n"; for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) { std::cerr << "\t\t" << FreqPairs[i].first << "\t"; - if (const char *CodeName = GetCodeName(FreqPairs[i].second, I->first)) + if (const char *CodeName = + GetCodeName(FreqPairs[i].second, I->first, StreamFile)) std::cerr << CodeName << "\n"; else std::cerr << "UnknownCode" << FreqPairs[i].second << "\n"; From gohman at apple.com Sun Apr 26 19:37:56 2009 From: gohman at apple.com (Dan Gohman) Date: Sun, 26 Apr 2009 17:37:56 -0700 Subject: [llvm-commits] [PATCH] Add GR8_H register class to X86 backend In-Reply-To: <74F36AB3-29C6-4FB0-8956-6F3CA337D62C@2pi.dk> References: <74F36AB3-29C6-4FB0-8956-6F3CA337D62C@2pi.dk> Message-ID: Thanks for pointing this out. This looks right to me. I'll apply the patch soon. Do you happen to have a testcase which shows the extra copies? Thanks, Dan On Apr 26, 2009, at 8:21 AM, Jakob Stoklund Olesen wrote: > X86RegisterInfo.td declares these register classes: > > def GR8_ : RegisterClass<"X86", [i8], 8, [AL, CL, DL, BL]> { > } > > def GR16_ : RegisterClass<"X86", [i16], 16, [AX, CX, DX, BX]> { > let SubRegClassList = [GR8_, GR8_]; > } > > The SubRegClassList asserts that EXTRACT_SUBREG GR16_, 2 yields a > GR8_ register. This is inconsistent with the actual SubRegSet: > > def : SubRegSet<2, [AX, CX, DX, BX], > [AH, CH, DH, BH]>; > > The SubRegClassList is currently only used by > ScheduleDAGSDNodesEmit.cpp to determine the register class of > virtual registers defined by EXTRACT_SUBREG. If these badly classed > virtual registers survive register coalescing, they cause > unnecessary copies in the LowerSubregs pass. > > The attached patch replaces the GR8_ register class with two > register classes: GR8_L and GR8_H, corresponding to the low and high > halves of the GR16_ registers. > > The patch passes "make check". > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From nicholas at mxc.ca Sun Apr 26 19:57:36 2009 From: nicholas at mxc.ca (Nick Lewycky) Date: Sun, 26 Apr 2009 17:57:36 -0700 Subject: [llvm-commits] [llvm] r69952 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/CellSPU/ lib/Target/PowerPC/ lib/Target/X86/ test/CodeGen/X86/ utils/TableGen/ In-Reply-To: <0EA9B983-1FF8-41E6-8F54-0600E13BB57B@me.com> References: <49F2B0DD.7000408@mxc.ca> <0EA9B983-1FF8-41E6-8F54-0600E13BB57B@me.com> Message-ID: <49F50300.2060905@mxc.ca> Nate Begeman wrote: > On Apr 24, 2009, at 11:42 PM, Nick Lewycky wrote: > >> Nate Begeman wrote: >>> Duncan / Rafael: >>> >>> What are you seeing for these tests that fail? I don't have a linux >>> machine to test on, and none of the automated builders complained. >> Yes they did. Here's one such example: >> >> http://google1.osuosl.org:8011/builders/clang-x86_64-linux/builds/1818/steps/test-llvm/logs/stdio > > Thanks for the link Nick, the IRC connection must have been down or > something, since nothing showed up in #llvm (the buildbots usually > complain there). The builder was already failing. It had one failure and went up to five, so it didn't notify because it didn't transition from successful to failing. Let me know if I can help you debug! Nick >> The four failures your patch introduced being >> CodeGen/Generic/vector-casts.ll, CodeGen/X86/mmx-arith.ll, >> CodeGen/X86/vec_set.ll and CodeGen/X86/vec_shuffle-6.ll. > > I've reworked a bit of the patch based on duncan's feedback, but I > can't get these tests to fail before or after my revisions using a > linux target triple on my darwin machine. I'll see if i can track > down a linux machine to test on. > > Nate > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From gohman at apple.com Sun Apr 26 19:57:59 2009 From: gohman at apple.com (Dan Gohman) Date: Sun, 26 Apr 2009 17:57:59 -0700 Subject: [llvm-commits] [llvm] r69948 - /llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp In-Reply-To: <200904240820.11695.baldrick@free.fr> References: <200904240240.n3O2eNMY032245@zion.cs.uiuc.edu> <200904240820.11695.baldrick@free.fr> Message-ID: <85AA5852-71D4-421D-8626-B37A61DB61C7@apple.com> On Apr 23, 2009, at 11:20 PM, Duncan Sands wrote: > Hi Dan, > >> Instead of requiring TLI.LowerCallTo to return an ISD::BUILD_PAIR, >> use ISD::EXTRACT_ELEMENT. SelectionDAG has a special fast-path for >> the cast of an EXTRACT_ELEMENT with a BUILD_PAIR operand, for the >> common case. > > maybe these routines could be factorized somehow? Done. Thanks for the review! Dan From clattner at apple.com Sun Apr 26 20:21:50 2009 From: clattner at apple.com (Chris Lattner) Date: Sun, 26 Apr 2009 18:21:50 -0700 Subject: [llvm-commits] [llvm] r69946 - in /llvm/trunk: docs/LangRef.html lib/Transforms/Scalar/InstructionCombining.cpp lib/VMCore/Type.cpp In-Reply-To: <49F4100D.50807@microchip.com> References: <200904240237.n3O2bsqj032157@zion.cs.uiuc.edu> <455CA6D2-CDBA-4A16-80E2-DF7F898948A7@apple.com> <49F4100D.50807@microchip.com> Message-ID: <464F6C59-BCF4-43AD-88A4-462120F9B859@apple.com> On Apr 26, 2009, at 12:41 AM, Sanjiv Gupta wrote: > I think the assembler and dis-assembler never bothered to call > sequentialType::indexValid. This test case always used to work. > Its only the clang and the opt that check the validity. > > But anyways there is a disconnect here between various tools and the > documentation. I think we should allow all types of integer indices > and change the documentation and code accordingly. I will do that. Sounds great, thanks! > Meanwhile, do you think we might have a similar case for > structType::indexValid. Adding a test case for that as well will be > a good idea. I think it is reasonable to restrict struct indices to always be 32- bits. They don't have anything to do with computable values on the target, they really are just indexes. -Chris From sabre at nondot.org Sun Apr 26 20:28:23 2009 From: sabre at nondot.org (Chris Lattner) Date: Sun, 26 Apr 2009 20:28:23 -0500 Subject: [llvm-commits] CVS: llvm-www/ProjectsWithLLVM/index.html Message-ID: <200904270128.n3R1SNnZ001935@zion.cs.uiuc.edu> Changes in directory llvm-www/ProjectsWithLLVM: index.html updated: 1.47 -> 1.48 --- Log message: Add TTA-based Codesign Environment (TCE) --- Diffs of the changes: (+27 -0) index.html | 27 +++++++++++++++++++++++++++ 1 files changed, 27 insertions(+) Index: llvm-www/ProjectsWithLLVM/index.html diff -u llvm-www/ProjectsWithLLVM/index.html:1.47 llvm-www/ProjectsWithLLVM/index.html:1.48 --- llvm-www/ProjectsWithLLVM/index.html:1.47 Thu Mar 26 11:54:50 2009 +++ llvm-www/ProjectsWithLLVM/index.html Sun Apr 26 20:27:24 2009 @@ -35,6 +35,7 @@

    + + + +
    +By the Flexible Design Methodologies for Application Specific Processors (FlexASP) Team +
    + +
    +

    +TCE is a toolset for designing +application-specific processors (ASP) based on +the Transport triggered architecture (TTA). The toolset provides a complete +co-design flow from C programs down to synthesizable VHDL and parallel program +binaries. Processor customization points include the register files, function +units, supported operations, and the interconnection network.

    + +

    +TCE uses llvm-gcc and LLVM for C language support, target independent +optimizations and also for parts of code generation. TCE generates new +LLVM-based code generators "on the fly" for the designed TTA processors and +loads them in to the compiler backend as runtime libraries to avoid per-target +recompilation of larger parts of the compiler chain. +

    +
    From gohman at apple.com Sun Apr 26 20:30:38 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 27 Apr 2009 01:30:38 -0000 Subject: [llvm-commits] [llvm] r70175 - /llvm/trunk/tools/bugpoint/bugpoint.cpp Message-ID: <200904270130.n3R1Uc58002046@zion.cs.uiuc.edu> Author: djg Date: Sun Apr 26 20:30:37 2009 New Revision: 70175 URL: http://llvm.org/viewvc/llvm-project?rev=70175&view=rev Log: Improve bugpoint's error messages when it runs out of memory, or when some other std::exception is thrown. Modified: llvm/trunk/tools/bugpoint/bugpoint.cpp Modified: llvm/trunk/tools/bugpoint/bugpoint.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/bugpoint/bugpoint.cpp?rev=70175&r1=70174&r2=70175&view=diff ============================================================================== --- llvm/trunk/tools/bugpoint/bugpoint.cpp (original) +++ llvm/trunk/tools/bugpoint/bugpoint.cpp Sun Apr 26 20:30:37 2009 @@ -88,6 +88,14 @@ std::cerr << "Tool execution error: " << TEE.what() << '\n'; } catch (const std::string& msg) { std::cerr << argv[0] << ": " << msg << "\n"; + } catch (const std::bad_alloc &e) { + std::cerr << "Oh no, a bugpoint process ran out of memory!\n" + "To increase the allocation limits for bugpoint child\n" + "processes, use the -mlimit option.\n"; + } catch (const std::exception &e) { + std::cerr << "Whoops, a std::exception leaked out of bugpoint: " + << e.what() << "\n" + << "This is a bug in bugpoint!\n"; } catch (...) { std::cerr << "Whoops, an exception leaked out of bugpoint. " << "This is a bug in bugpoint!\n"; From gohman at apple.com Sun Apr 26 20:41:10 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 27 Apr 2009 01:41:10 -0000 Subject: [llvm-commits] [llvm] r70176 - in /llvm/trunk: lib/Analysis/ScalarEvolution.cpp test/Transforms/IndVarSimplify/avoid-i0.ll Message-ID: <200904270141.n3R1fBUZ002383@zion.cs.uiuc.edu> Author: djg Date: Sun Apr 26 20:41:10 2009 New Revision: 70176 URL: http://llvm.org/viewvc/llvm-project?rev=70176&view=rev Log: Handle ands with ~0 correctly too. This fixes PR4052. Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=70176&r1=70175&r2=70176&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Sun Apr 26 20:41:10 2009 @@ -1756,6 +1756,8 @@ if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { if (CI->isNullValue()) return getSCEV(U->getOperand(1)); + if (CI->isAllOnesValue()) + return getSCEV(U->getOperand(0)); const APInt &A = CI->getValue(); unsigned Ones = A.countTrailingOnes(); if (APIntOps::isMask(Ones, A)) Modified: llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll?rev=70176&r1=70175&r2=70176&view=diff ============================================================================== --- llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll (original) +++ llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll Sun Apr 26 20:41:10 2009 @@ -1,4 +1,5 @@ ; RUN: llvm-as < %s | opt -indvars +; PR4052 ; PR4054 ; Don't treat an and with 0 as a mask (trunc+zext). @@ -21,3 +22,105 @@ %0 = and i8 0, 0 ; [#uses=1] br label %bb } + + at x = common global i32 0 ; [#uses=1] + +define signext i8 @safe_sub_func_int32_t_s_s(i32 %_si1, i8 signext %_si2) nounwind { +entry: + %_si1_addr = alloca i32 ; [#uses=3] + %_si2_addr = alloca i8 ; [#uses=3] + %retval = alloca i32 ; [#uses=2] + %0 = alloca i32 ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 %_si1, i32* %_si1_addr + store i8 %_si2, i8* %_si2_addr + %1 = load i8* %_si2_addr, align 1 ; [#uses=1] + %2 = sext i8 %1 to i32 ; [#uses=1] + %3 = load i32* %_si1_addr, align 4 ; [#uses=1] + %4 = xor i32 %2, %3 ; [#uses=1] + %5 = load i8* %_si2_addr, align 1 ; [#uses=1] + %6 = sext i8 %5 to i32 ; [#uses=1] + %7 = sub i32 7, %6 ; [#uses=1] + %8 = load i32* %_si1_addr, align 4 ; [#uses=1] + %9 = shl i32 %8, %7 ; [#uses=1] + %10 = and i32 %4, %9 ; [#uses=1] + %11 = icmp slt i32 %10, 0 ; [#uses=1] + %12 = zext i1 %11 to i32 ; [#uses=1] + store i32 %12, i32* %0, align 4 + %13 = load i32* %0, align 4 ; [#uses=1] + store i32 %13, i32* %retval, align 4 + br label %return + +return: ; preds = %entry + %retval1 = load i32* %retval ; [#uses=1] + %retval12 = trunc i32 %retval1 to i8 ; [#uses=1] + ret i8 %retval12 +} + +define i32 @safe_sub_func_uint64_t_u_u(i32 %_ui1, i32 %_ui2) nounwind { +entry: + %_ui1_addr = alloca i32 ; [#uses=2] + %_ui2_addr = alloca i32 ; [#uses=1] + %retval = alloca i32 ; [#uses=2] + %0 = alloca i32 ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 %_ui1, i32* %_ui1_addr + store i32 %_ui2, i32* %_ui2_addr + %1 = load i32* %_ui1_addr, align 4 ; [#uses=1] + %2 = sub i32 %1, 1 ; [#uses=1] + store i32 %2, i32* %0, align 4 + %3 = load i32* %0, align 4 ; [#uses=1] + store i32 %3, i32* %retval, align 4 + br label %return + +return: ; preds = %entry + %retval1 = load i32* %retval ; [#uses=1] + ret i32 %retval1 +} + +define void @int87(i8 signext %p_48, i8 signext %p_49) nounwind { +entry: + %p_48_addr = alloca i8 ; [#uses=1] + %p_49_addr = alloca i8 ; [#uses=1] + %l_52 = alloca i32 ; [#uses=7] + %vol.0 = alloca i32 ; [#uses=1] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i8 %p_48, i8* %p_48_addr + store i8 %p_49, i8* %p_49_addr + br label %bb4 + +bb: ; preds = %bb4 + %0 = volatile load i32* @x, align 4 ; [#uses=1] + store i32 %0, i32* %vol.0, align 4 + store i32 0, i32* %l_52, align 4 + br label %bb2 + +bb1: ; preds = %bb2 + %1 = load i32* %l_52, align 4 ; [#uses=1] + %2 = call i32 @safe_sub_func_uint64_t_u_u(i32 %1, i32 1) nounwind ; [#uses=1] + store i32 %2, i32* %l_52, align 4 + br label %bb2 + +bb2: ; preds = %bb1, %bb + %3 = load i32* %l_52, align 4 ; [#uses=1] + %4 = icmp eq i32 %3, 0 ; [#uses=1] + br i1 %4, label %bb1, label %bb3 + +bb3: ; preds = %bb2 + %5 = load i32* %l_52, align 4 ; [#uses=1] + %6 = call signext i8 @safe_sub_func_int32_t_s_s(i32 %5, i8 signext 1) nounwind ; [#uses=1] + %7 = sext i8 %6 to i32 ; [#uses=1] + store i32 %7, i32* %l_52, align 4 + br label %bb4 + +bb4: ; preds = %bb3, %entry + %8 = load i32* %l_52, align 4 ; [#uses=1] + %9 = icmp ne i32 %8, 0 ; [#uses=1] + br i1 %9, label %bb, label %bb5 + +bb5: ; preds = %bb4 + br label %return + +return: ; preds = %bb5 + ret void +} From gohman at apple.com Sun Apr 26 21:00:55 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 27 Apr 2009 02:00:55 -0000 Subject: [llvm-commits] [llvm] r70179 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/fold-sext-trunc.ll Message-ID: <200904270200.n3R20txx002997@zion.cs.uiuc.edu> Author: djg Date: Sun Apr 26 21:00:55 2009 New Revision: 70179 URL: http://llvm.org/viewvc/llvm-project?rev=70179&view=rev Log: When transforming sext(trunc(load(x))) into sext(smaller load(x)), the trunc is directly replaced with the smaller load, so don't try to create a new sext node. This fixes PR4050. Added: llvm/trunk/test/CodeGen/X86/fold-sext-trunc.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=70179&r1=70178&r2=70179&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Sun Apr 26 21:00:55 2009 @@ -2962,7 +2962,7 @@ if (NarrowLoad.getNode()) { if (NarrowLoad.getNode() != N0.getNode()) CombineTo(N0.getNode(), NarrowLoad); - return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, NarrowLoad); + return SDValue(N, 0); // Return N so it doesn't get rechecked! } // See if the value being truncated is already sign extended. If so, just Added: llvm/trunk/test/CodeGen/X86/fold-sext-trunc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fold-sext-trunc.ll?rev=70179&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/fold-sext-trunc.ll (added) +++ llvm/trunk/test/CodeGen/X86/fold-sext-trunc.ll Sun Apr 26 21:00:55 2009 @@ -0,0 +1,20 @@ +; RUN: llvm-as < %s | llc -march=x86-64 | grep movslq | count 1 +; PR4050 + + type { i64 } ; type %0 + %struct.S1 = type { i16, i32 } + at g_10 = external global %struct.S1 ; <%struct.S1*> [#uses=2] + +declare void @func_28(i64, i64) + +define void @int322(i32 %foo) nounwind { +entry: + %val = load i64* getelementptr (%0* bitcast (%struct.S1* @g_10 to %0*), i32 0, i32 0) ; [#uses=1] + %0 = load i32* getelementptr (%struct.S1* @g_10, i32 0, i32 1), align 4 ; [#uses=1] + %1 = sext i32 %0 to i64 ; [#uses=1] + %tmp4.i = lshr i64 %val, 32 ; [#uses=1] + %tmp5.i = trunc i64 %tmp4.i to i32 ; [#uses=1] + %2 = sext i32 %tmp5.i to i64 ; [#uses=1] + tail call void @func_28(i64 %2, i64 %1) nounwind + ret void +} From gohman at apple.com Sun Apr 26 22:05:27 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 27 Apr 2009 03:05:27 -0000 Subject: [llvm-commits] [llvm] r70180 - /llvm/trunk/test/Assembler/2002-04-07-InfConstant.ll Message-ID: <200904270305.n3R35Rr7005038@zion.cs.uiuc.edu> Author: djg Date: Sun Apr 26 22:05:26 2009 New Revision: 70180 URL: http://llvm.org/viewvc/llvm-project?rev=70180&view=rev Log: Make this test slightly more strict. Modified: llvm/trunk/test/Assembler/2002-04-07-InfConstant.ll Modified: llvm/trunk/test/Assembler/2002-04-07-InfConstant.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/2002-04-07-InfConstant.ll?rev=70180&r1=70179&r2=70180&view=diff ============================================================================== --- llvm/trunk/test/Assembler/2002-04-07-InfConstant.ll (original) +++ llvm/trunk/test/Assembler/2002-04-07-InfConstant.ll Sun Apr 26 22:05:26 2009 @@ -1,6 +1,6 @@ ; The output formater prints out 1.0e100 as Inf! ; -; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | grep 0x7FF0000000000000 define float @test() { %tmp = mul float 0x7FF0000000000000, 1.000000e+01 ; [#uses=1] From sanjiv.gupta at microchip.com Sun Apr 26 22:21:10 2009 From: sanjiv.gupta at microchip.com (Sanjiv Gupta) Date: Mon, 27 Apr 2009 03:21:10 -0000 Subject: [llvm-commits] [llvm] r70181 - /llvm/trunk/docs/LangRef.html Message-ID: <200904270321.n3R3LCnv005449@zion.cs.uiuc.edu> Author: sgupta Date: Sun Apr 26 22:21:00 2009 New Revision: 70181 URL: http://llvm.org/viewvc/llvm-project?rev=70181&view=rev Log: Now that any size of integer indices are allowed for sequential types, remove the unneccessary gyan about promoting them. Modified: llvm/trunk/docs/LangRef.html Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=70181&r1=70180&r2=70181&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Sun Apr 26 22:21:00 2009 @@ -3629,9 +3629,7 @@

    The type of each index argument depends on the type it is indexing into. When indexing into a (packed) structure, only i32 integer constants are allowed. When indexing into an array, pointer or vector, -integers of any width are allowed (also non-constants). 16-bit -values will be sign extended to 32-bits if required, and 32-bit values -will be sign extended to 64-bits if required.

    +integers of any width are allowed (also non-constants).

    For example, let's consider a C code fragment and how it gets compiled to LLVM:

    From jyasskin at google.com Sun Apr 26 23:31:19 2009 From: jyasskin at google.com (Jeffrey Yasskin) Date: Sun, 26 Apr 2009 21:31:19 -0700 Subject: [llvm-commits] Tests for WeakVH and AssertingVH Message-ID: In preparation for writing CallbackVH, I figured it'd be nice for WeakVH and AssertingVH to have tests. These pointed out that the overloads for the comparison operators were not only unnecessary in the presence of the implicit conversion; they caused ambiguous overload errors. So I deleted them. Jeffrey -------------- next part -------------- A non-text attachment was scrubbed... Name: ValueHandle_tests.patch Type: application/octet-stream Size: 8795 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20090426/278082cd/attachment.obj From clattner at apple.com Sun Apr 26 23:36:05 2009 From: clattner at apple.com (Chris Lattner) Date: Sun, 26 Apr 2009 21:36:05 -0700 Subject: [llvm-commits] Tests for WeakVH and AssertingVH In-Reply-To: References: Message-ID: <19F86ABC-29C0-406C-A6A6-EC781E54887C@apple.com> On Apr 26, 2009, at 9:31 PM, Jeffrey Yasskin wrote: > In preparation for writing CallbackVH, I figured it'd be nice for > WeakVH and AssertingVH to have tests. These pointed out that the > overloads for the comparison operators were not only unnecessary in > the presence of the implicit conversion; they caused ambiguous > overload errors. So I deleted them. Looks good, please commit! -Chris From sabre at nondot.org Sun Apr 26 23:49:30 2009 From: sabre at nondot.org (Chris Lattner) Date: Mon, 27 Apr 2009 04:49:30 -0000 Subject: [llvm-commits] [test-suite] r70182 - /test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c Message-ID: <200904270449.n3R4nVZH008098@zion.cs.uiuc.edu> Author: lattner Date: Sun Apr 26 23:49:30 2009 New Revision: 70182 URL: http://llvm.org/viewvc/llvm-project?rev=70182&view=rev Log: add a testcase for rdar://6828787 Modified: test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c Modified: test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c?rev=70182&r1=70181&r2=70182&view=diff ============================================================================== --- test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c (original) +++ test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c Sun Apr 26 23:49:30 2009 @@ -121,6 +121,22 @@ return z; } + +//===- rdar://6828787 -----------------------------------------------------===// + +#pragma pack(4) + +struct foo2 { + short a; + long x; + short y; +}; + +#pragma pack() + +struct foo2 foo2 = { 23122, -12312731, -312 }; + + //===- Checker ------------------------------------------------------------===// int main() { @@ -128,7 +144,7 @@ spinlock_t lock; printf("PR156: %s\n", init_task_union.task.comm); printf("PR295/PR568: %d, %d\n", fixed_tl[0].word.pad, fixed_tl[0].base); - printf("PR574: %d, %d, %d, %d\n", bkv4.gv4.av4, cav1.dv1, cav1.ev1, + printf("PR574: %d, %d, %d, %d\n", (int)bkv4.gv4.av4, cav1.dv1, cav1.ev1, cav1.fv1[0]); printf("PR162: %d, %d, %d\n", V.X.A, V.X.B, V.C); printf("PR650: %s, %d\n", nd.data, nd.alignmentDummy); @@ -141,8 +157,9 @@ printf("PR654: %p, '%s'\n", s.inplace, s.chunk_data); printf("PR323: %d, '%s'\n", ai.lsk.agid, ai.lsk.key); lock = (spinlock_t) { .raw_lock = one_raw_spinlock() }; - printf("PR627: %d\n", sizeof(lock)); + printf("PR627: %d\n", (int)sizeof(lock)); XX = ucast_test(); printf("PR684: %d, %d, %d %d\n", XX.s.i1, XX.s.i2, XX.s.i3, XX.i); + printf("rdar://6828787: %d, %d, %d\n", foo2.a, foo2.x, foo2.y); return 0; } From sabre at nondot.org Sun Apr 26 23:50:23 2009 From: sabre at nondot.org (Chris Lattner) Date: Mon, 27 Apr 2009 04:50:23 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r70183 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Message-ID: <200904270450.n3R4oNgm008139@zion.cs.uiuc.edu> Author: lattner Date: Sun Apr 26 23:50:22 2009 New Revision: 70183 URL: http://llvm.org/viewvc/llvm-project?rev=70183&view=rev Log: Fix rdar://6828787 (whose testcase was added to test/SingleSource/UnitTests/2006-01-23-UnionInit.c) When a structure is converted to packed, the alignment of the llvm field should be reset to 1 because packed fields' alignments are not taken into consideration. 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=70183&r1=70182&r2=70183&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Sun Apr 26 23:50:22 2009 @@ -6897,6 +6897,7 @@ // Switch to packed. ConvertToPacked(); LLVMNaturalByteOffset = NextFieldByteStart; + ValLLVMAlign = 1; assert(LLVMNaturalByteOffset*8 <= GCCFieldOffsetInBits && "Packing didn't fix the problem!"); } From sabre at nondot.org Sun Apr 26 23:56:44 2009 From: sabre at nondot.org (Chris Lattner) Date: Mon, 27 Apr 2009 04:56:44 -0000 Subject: [llvm-commits] [test-suite] r70184 - /test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c Message-ID: <200904270456.n3R4uiDr008348@zion.cs.uiuc.edu> Author: lattner Date: Sun Apr 26 23:56:43 2009 New Revision: 70184 URL: http://llvm.org/viewvc/llvm-project?rev=70184&view=rev Log: cast long to int for %d Modified: test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c Modified: test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c?rev=70184&r1=70183&r2=70184&view=diff ============================================================================== --- test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c (original) +++ test-suite/trunk/SingleSource/UnitTests/2006-01-23-UnionInit.c Sun Apr 26 23:56:43 2009 @@ -160,6 +160,6 @@ printf("PR627: %d\n", (int)sizeof(lock)); XX = ucast_test(); printf("PR684: %d, %d, %d %d\n", XX.s.i1, XX.s.i2, XX.s.i3, XX.i); - printf("rdar://6828787: %d, %d, %d\n", foo2.a, foo2.x, foo2.y); + printf("rdar://6828787: %d, %d, %d\n", foo2.a, (int)foo2.x, foo2.y); return 0; }