Fix instrumentation regressions for libc-2.29 on ARM (#653)
[dyninst.git] / dataflowAPI / src / liveness.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 // $Id: liveness.C,v 1.12 2008/09/04 21:06:20 bill Exp $
32
33 #include "debug_dataflow.h"
34 #include "parseAPI/h/CFG.h"
35 #include "parseAPI/h/Location.h"
36 #include "instructionAPI/h/InstructionDecoder.h"
37 #include "instructionAPI/h/Register.h"
38 #include "instructionAPI/h/Instruction.h"
39
40 #include "dataflowAPI/h/liveness.h"
41 #include "dataflowAPI/h/ABI.h"
42 #include <boost/bind.hpp>
43
44 std::string regs1 = " ttttttttddddddddcccccccmxxxxxxxxxxxxxxxxgf                  rrrrrrrrrrrrrrrrr";
45 std::string regs2 = " rrrrrrrrrrrrrrrrrrrrrrrm1111110000000000ssoscgfedrnoditszapci11111100dsbsbdca";
46 std::string regs3 = " 7654321076543210765432105432109876543210bbrssssssftfffffffffp54321098iippxxxx";
47
48 using namespace std;
49 using namespace Dyninst;
50 using namespace Dyninst::ParseAPI;
51 using namespace Dyninst::InstructionAPI;
52
53 // Code for register liveness detection
54
55 LivenessAnalyzer::LivenessAnalyzer(int w): errorno((ErrorType)-1) {
56     width = w;
57     abi = ABI::getABI(width);
58 }
59
60 int LivenessAnalyzer::getIndex(MachRegister machReg){
61    return abi->getIndex(machReg);
62 }
63
64 const bitArray& LivenessAnalyzer::getLivenessIn(Block *block) {
65     // Calculate if it hasn't been done already
66     liveness_cerr << endl << "LivenessAnalyzer::getLivenessIn()" << endl;
67     liveness_cerr << "Getting liveness for block " << hex << block->start() << dec << endl;
68     assert(blockLiveInfo.find(block) != blockLiveInfo.end());
69     livenessData& data = blockLiveInfo[block];
70     assert(data.in.size());
71     return data.in;
72 }
73
74 void LivenessAnalyzer::processEdgeLiveness(Edge* e, livenessData& data, Block* block,
75                                            const bitArray& allRegsDefined)
76 {
77   // covered by Intraproc predicate
78   //if ((*eit)->type() == CALL) continue;
79   // Is this correct?
80   if (e->type() == CATCH) return;
81   if (e->sinkEdge()) {
82     liveness_cerr << "Sink edge from " << hex << block->start() << dec << endl;
83     data.out |= allRegsDefined;
84     return;
85   }
86   
87   // TODO: multiple entry functions and you?
88   data.out |= getLivenessIn(e->trg());
89   liveness_cerr << "Accumulating from block " << hex << (e->trg())->start() << dec << endl;
90   liveness_cerr << data.out << endl;
91 }
92
93
94 const bitArray& LivenessAnalyzer::getLivenessOut(Block *block, bitArray &allRegsDefined) {
95        
96         assert(blockLiveInfo.find(block) != blockLiveInfo.end());
97         livenessData &data = blockLiveInfo[block];
98         data.out = bitArray(data.in.size());
99         assert(data.out.size());
100         // ignore call, return edges
101         Intraproc epred;
102         
103
104     // OUT(X) = UNION(IN(Y)) for all successors Y of X
105     boost::lock_guard<Block> g(*block);
106     const Block::edgelist & target_edges = block -> targets();
107
108     liveness_cerr << "getLivenessOut for block [" << hex << block->start() << "," << block->end() << "]" << dec << endl;
109     
110
111     std::for_each(boost::make_filter_iterator(epred, target_edges.begin(), target_edges.end()),
112                   boost::make_filter_iterator(epred, target_edges.end(), target_edges.end()),
113                   boost::bind(&LivenessAnalyzer::processEdgeLiveness, 
114                               this, 
115                               _1, 
116                               boost::ref(data), 
117                               block,
118                               boost::ref(allRegsDefined)));
119     
120     liveness_cerr << " Returning liveness for out " << endl;
121     liveness_cerr << "  " << data.out << endl;
122
123
124     return data.out;
125 }
126
127 void LivenessAnalyzer::summarizeBlockLivenessInfo(Function* func, Block *block, bitArray &allRegsDefined) 
128 {
129    if (blockLiveInfo.find(block) != blockLiveInfo.end()){
130         return;
131    }
132    liveness_printf("\tsummarize block info at block %lx\n", block->start());
133  
134    livenessData &data = blockLiveInfo[block];
135    data.use = data.def = data.in = abi->getBitArray();
136
137    using namespace Dyninst::InstructionAPI;
138    Address current = block->start();
139    InstructionDecoder decoder(
140                        reinterpret_cast<const unsigned char*>(getPtrToInstruction(block, block->start())),                   
141                        block->size(),
142                        block->obj()->cs()->getArch());
143    Instruction curInsn = decoder.decode();
144    while(curInsn.isValid()) {
145      ReadWriteInfo curInsnRW;
146      liveness_printf("%s[%d] After instruction %s at address 0x%lx:\n",
147                      FILE__, __LINE__, curInsn.format().c_str(), current);
148      if(!cachedLivenessInfo.getLivenessInfo(current, func, curInsnRW))
149      {
150        curInsnRW = calcRWSets(curInsn, block, current);
151        cachedLivenessInfo.insertInstructionInfo(current, curInsnRW, func);
152      }
153
154      data.use |= (curInsnRW.read & ~data.def);
155      // And if written, then was defined
156      data.def |= curInsnRW.written;
157       
158      liveness_printf("%s[%d] After instruction at address 0x%lx:\n",
159                      FILE__, __LINE__, current);
160      liveness_cerr << "        " << regs1 << endl;
161      liveness_cerr << "        " << regs2 << endl;
162      liveness_cerr << "        " << regs3 << endl;
163      liveness_cerr << "Read    " << curInsnRW.read << endl;
164      liveness_cerr << "Written " << curInsnRW.written << endl;
165      liveness_cerr << "Used    " << data.use << endl;
166      liveness_cerr << "Defined " << data.def << endl;
167
168       current += curInsn.size();
169       curInsn = decoder.decode();
170    }
171
172    liveness_printf("%s[%d] Liveness summary for block:\n", FILE__, __LINE__);
173    liveness_cerr << "     " << regs1 << endl;
174    liveness_cerr << "     " << regs2 << endl;
175    liveness_cerr << "     " << regs3 << endl;
176    liveness_cerr << "Used " << data.in << endl;
177    liveness_cerr << "Def  " << data.def << endl;
178    liveness_cerr << "Use  " << data.use << endl;
179    liveness_printf("%s[%d] --------------------\n---------------------\n", FILE__, __LINE__);
180
181    allRegsDefined |= data.def;
182
183    return;
184 }
185
186 /* This is used to do fixed point iteration until 
187    the in and out don't change anymore */
188 bool LivenessAnalyzer::updateBlockLivenessInfo(Block* block, bitArray &allRegsDefined) 
189 {
190   bool change = false;
191   livenessData &data = blockLiveInfo[block];
192
193   // old_IN = IN(X)
194   bitArray oldIn = data.in;
195   // tmp is an accumulator
196   getLivenessOut(block, allRegsDefined);
197   
198   // Liveness is a reverse dataflow algorithm
199  
200   // OUT(X) = UNION(IN(Y)) for all successors Y of X
201
202   // IN(X) = USE(X) + (OUT(X) - DEF(X))
203   liveness_cerr << "Updating block info for block " << hex << block->start() << dec << endl;
204   liveness_cerr << "     " << regs1 << endl;
205   liveness_cerr << "     " << regs2 << endl;
206   liveness_cerr << "     " << regs3 << endl;
207   liveness_cerr << "Out: " << data.out << endl;
208   liveness_cerr << "Def: " << data.def << endl;
209   liveness_cerr << "Use: " << data.use << endl;
210   data.in = data.use | (data.out - data.def);
211   liveness_cerr << "In:  " << data.in << endl;
212   
213   // if (old_IN != IN(X)) then change = true
214   if (data.in != oldIn)
215       change = true;
216       
217   return change;
218 }
219
220 // Calculate basic block summaries of liveness information
221
222 void LivenessAnalyzer::analyze(Function *func) {
223     if (liveFuncCalculated.find(func) != liveFuncCalculated.end()) return;
224     liveness_printf("Caculate basic block level liveness information for function %s (%lx)\n", func->name().c_str(), func->addr());
225
226     // Step 0: initialize the "registers this function has defined" bitarray
227     assert(funcRegsDefined.find(func) == funcRegsDefined.end());
228     // Let's assume the regs that are normally live at the entry to a function
229     // are the regs a call can read.
230     funcRegsDefined[func] = abi->getCallReadRegisters();
231     bitArray &regsDefined = funcRegsDefined[func];
232
233     // Step 1: gather the block summaries
234     Function::blocklist::iterator sit = func->blocks().begin();
235     for( ; sit != func->blocks().end(); sit++) {
236        summarizeBlockLivenessInfo(func,*sit, regsDefined);
237     }
238     
239     // Step 2: We now have block-level summaries of gen/kill info
240     // within the block. Propagate this via standard fixpoint
241     // calculation
242     bool changed = true;
243     while (changed) {
244         changed = false;
245         for(sit = func->blocks().begin(); sit != func->blocks().end(); sit++) {
246            if (updateBlockLivenessInfo(*sit, regsDefined)) {
247                 changed = true;
248             }
249         }
250     }
251
252     liveFuncCalculated[func] = true;
253 }
254
255
256 // This function does two things.
257 // First, it does a backwards iteration over instructions in its
258 // block to calculate its liveness.
259 // At the same time, we cache liveness (which was calculated) in
260 // any instPoints we cover. Since an iP only exists if the user
261 // asked for it, we take its existence to indicate that they'll
262 // also be instrumenting. 
263 bool LivenessAnalyzer::query(Location loc, Type type, bitArray &bitarray) {
264 //TODO: consider the trustness of the location 
265
266    if (!loc.isValid()){
267         errorno = Invalid_Location;
268         return false;
269    }
270
271    // First, ensure that the block liveness is done.
272    analyze(loc.func);
273
274    Address addr = 0;
275    // For "pre"-instruction we subtract one from the address. This is done
276    // because liveness is calculated backwards; therefore, accumulating
277    // up to <addr> is actually the liveness _after_ that instruction, not
278    // before. Since we compare using > below, -1 means it will trigger. 
279
280    switch(loc.type) {
281       // First, don't be dumb if we're looking at (effectively) an initial
282       // instruction of a CFG element.
283       case Location::function_:
284          if (type == Before){
285                 bitarray = getLivenessIn(loc.func->entry());
286                 return true;
287          }
288          assert(0);
289       case Location::block_:
290
291       case Location::blockInstance_:
292          
293          if (type == Before) {
294                 bitarray = getLivenessIn(loc.block);
295                 return true;
296          }
297          addr = loc.block->lastInsnAddr()-1;
298          break;
299
300       case Location::instruction_:
301
302       case Location::instructionInstance_:
303
304          if (type == Before) {
305                 if (loc.offset == loc.block->start()) {
306                         bitarray = getLivenessIn(loc.block);
307                         return true;
308                 }
309                 addr = loc.offset - 1;
310          }
311          if (type == After) {
312                 if (loc.offset == loc.block->lastInsnAddr()) {
313                    bitarray = blockLiveInfo[loc.block].out;
314                    return true;
315                 }
316                 addr = loc.offset;
317         }
318          break;
319
320       case Location::edge_:
321          bitarray = getLivenessIn(loc.edge->trg());
322          return true;
323       case Location::entry_:
324          if (type == Before) {
325                 bitarray = getLivenessIn(loc.block);
326                 return true;
327          }
328          assert(0);
329       case Location::call_:
330          if (type == Before) addr = loc.block->lastInsnAddr()-1;
331          if (type == After) {
332             bitarray = blockLiveInfo[loc.block].out;
333             return true;
334          }
335          break;
336       case Location::exit_:
337          if (type == After){
338                 addr = loc.block->lastInsnAddr()-1;
339                 break;
340          }
341          assert(0);
342
343       default:
344          assert(0);
345          
346   }
347         
348    // We know: 
349    //    liveness _out_ at the block level:
350    bitArray working = blockLiveInfo[loc.block].out;
351    assert(!working.empty());
352
353    // We now want to do liveness analysis for straight-line code. 
354         
355    using namespace Dyninst::InstructionAPI;
356     
357    Address blockBegin = loc.block->start();
358    Address blockEnd = loc.block->end();
359    std::vector<Address> blockAddrs;
360    
361    const unsigned char* insnBuffer = 
362       reinterpret_cast<const unsigned char*>(getPtrToInstruction(loc.block, blockBegin));
363    assert(insnBuffer);
364
365    InstructionDecoder decoder(insnBuffer,loc.block->size(),
366         loc.func->isrc()->getArch());
367    Address curInsnAddr = blockBegin;
368    do
369    {
370      ReadWriteInfo rw;
371      if(!cachedLivenessInfo.getLivenessInfo(curInsnAddr, loc.func, rw))
372      {
373         Instruction tmp = decoder.decode(insnBuffer);
374         rw = calcRWSets(tmp, loc.block, curInsnAddr);
375         cachedLivenessInfo.insertInstructionInfo(curInsnAddr, rw, loc.func);
376      }
377      blockAddrs.push_back(curInsnAddr);
378      curInsnAddr += rw.insnSize;
379      insnBuffer += rw.insnSize;
380    } while(curInsnAddr < blockEnd);
381     
382     
383    // We iterate backwards over instructions in the block, as liveness is 
384    // a backwards flow process.
385
386    std::vector<Address>::reverse_iterator current = blockAddrs.rbegin();
387
388    liveness_printf("%s[%d] instPoint calcLiveness: %d, 0x%lx, 0x%lx\n", 
389                    FILE__, __LINE__, current != blockAddrs.rend(), *current, addr);
390    
391    while(current != blockAddrs.rend() && *current > addr)
392    {
393       ReadWriteInfo rwAtCurrent;
394       if(!cachedLivenessInfo.getLivenessInfo(*current, loc.func, rwAtCurrent))
395          assert(0);
396
397       liveness_printf("%s[%d] Calculating liveness for iP 0x%lx, insn at 0x%lx\n",
398                       FILE__, __LINE__, addr, *current);
399       liveness_cerr << "Pre:    " << working << endl;
400       working &= (~rwAtCurrent.written);
401       working |= rwAtCurrent.read;
402       liveness_cerr << "Post:   " << working << endl;
403       liveness_cerr << "Current read:  " << rwAtCurrent.read << endl;
404       liveness_cerr << "Current Write: " << rwAtCurrent.written << endl;
405       
406       ++current;
407    }
408    assert(!working.empty());
409
410
411    bitarray = working;
412    return true;
413 }
414
415 bool LivenessAnalyzer::query(Location loc, Type type, const MachRegister& machReg, bool &live){
416         bitArray liveRegs;
417         if (query(loc, type, liveRegs)){
418         int index = getIndex(machReg);
419         assert(index >= 0);
420                 live = liveRegs[index];
421                 return true;
422         }
423         return false;
424
425 }
426
427
428 ReadWriteInfo LivenessAnalyzer::calcRWSets(Instruction curInsn, Block *blk, Address a)
429 {
430
431   liveness_cerr << "calcRWSets for " << curInsn.format() << " @ " << hex << a << dec << endl;
432   ReadWriteInfo ret;
433   ret.read = abi->getBitArray();
434   ret.written = abi->getBitArray();
435   ret.insnSize = curInsn.size();
436   std::set<RegisterAST::Ptr> cur_read, cur_written;
437   curInsn.getReadSet(cur_read);
438   curInsn.getWriteSet(cur_written);
439     liveness_printf("Read registers: \n");
440   
441   for (std::set<RegisterAST::Ptr>::const_iterator i = cur_read.begin(); 
442        i != cur_read.end(); i++) 
443   {
444     MachRegister cur = (*i)->getID();
445     if (cur.getArchitecture() == Arch_ppc64)
446         cur = MachRegister((cur.val() & ~Arch_ppc64) | Arch_ppc32);
447     liveness_printf("\t%s \n", cur.name().c_str());
448     MachRegister base = cur.getBaseRegister();
449     if (base == x86::flags || base == x86_64::flags){
450       if (width == 4){
451         ret.read[getIndex(x86::of)] = true;
452         ret.read[getIndex(x86::cf)] = true;
453         ret.read[getIndex(x86::pf)] = true;
454         ret.read[getIndex(x86::af)] = true;
455         ret.read[getIndex(x86::zf)] = true;
456         ret.read[getIndex(x86::sf)] = true;
457         ret.read[getIndex(x86::df)] = true;
458         ret.read[getIndex(x86::tf)] = true;
459         ret.read[getIndex(x86::nt_)] = true;
460       }
461       else {
462         ret.read[getIndex(x86_64::of)] = true;
463         ret.read[getIndex(x86_64::cf)] = true;
464         ret.read[getIndex(x86_64::pf)] = true;
465         ret.read[getIndex(x86_64::af)] = true;
466         ret.read[getIndex(x86_64::zf)] = true;
467         ret.read[getIndex(x86_64::sf)] = true;
468         ret.read[getIndex(x86_64::df)] = true;
469         ret.read[getIndex(x86_64::tf)] = true;
470         ret.read[getIndex(x86_64::nt_)] = true;
471       }
472     }
473     else{
474       base = changeIfMMX(base);
475       int index = getIndex(base);
476       //assert(index >= 0);
477       if(index>=0) ret.read[index] = true;
478     }
479   }
480   liveness_printf("Write Registers: \n"); 
481   for (std::set<RegisterAST::Ptr>::const_iterator i = cur_written.begin(); 
482        i != cur_written.end(); i++) {  
483     MachRegister cur = (*i)->getID();
484     if (cur.getArchitecture() == Arch_ppc64)
485         cur = MachRegister((cur.val() & ~Arch_ppc64) | Arch_ppc32);
486     liveness_printf("\t%s \n", cur.name().c_str());
487     MachRegister base = cur.getBaseRegister();
488     if (base == x86::flags || base == x86_64::flags){
489       if (width == 4){
490         ret.written[getIndex(x86::of)] = true;
491         ret.written[getIndex(x86::cf)] = true;
492         ret.written[getIndex(x86::pf)] = true;
493         ret.written[getIndex(x86::af)] = true;
494         ret.written[getIndex(x86::zf)] = true;
495         ret.written[getIndex(x86::sf)] = true;
496         ret.written[getIndex(x86::df)] = true;
497         ret.written[getIndex(x86::tf)] = true;
498         ret.written[getIndex(x86::nt_)] = true;
499       }
500       else {
501         ret.written[getIndex(x86_64::of)] = true;
502         ret.written[getIndex(x86_64::cf)] = true;
503         ret.written[getIndex(x86_64::pf)] = true;
504         ret.written[getIndex(x86_64::af)] = true;
505         ret.written[getIndex(x86_64::zf)] = true;
506         ret.written[getIndex(x86_64::sf)] = true;
507         ret.written[getIndex(x86_64::df)] = true;
508         ret.written[getIndex(x86_64::tf)] = true;
509         ret.written[getIndex(x86_64::nt_)] = true;
510       }
511     }
512     else{
513       base = changeIfMMX(base);
514       int index = getIndex(base);
515       //assert(index >= 0);
516       if(index>=0){
517           ret.written[index] = true;
518           if ((cur != base && cur.size() < 4) || isMMX(base)) ret.read[index] = true;
519       }
520     }
521   }
522   InsnCategory category = curInsn.getCategory();
523   switch(category)
524   {
525   case c_CallInsn:
526       // Call instructions not at the end of a block are thunks, which are not ABI-compliant.
527       // So make conservative assumptions about what they may read (ABI) but don't assume they write anything.
528       ret.read |= (abi->getCallReadRegisters());
529       if(blk->lastInsnAddr() == a)
530       {
531           ret.written |= (abi->getCallWrittenRegisters());
532       }
533     break;
534   case c_ReturnInsn:
535     ret.read |= (abi->getReturnReadRegisters());
536     // Nothing written implicitly by a return
537     break;
538   case c_BranchInsn:
539     if(!curInsn.allowsFallThrough() && isExitBlock(blk))
540     {
541       //Tail call, union of call and return
542       ret.read |= ((abi->getCallReadRegisters()) |
543                    (abi->getReturnReadRegisters()));
544       ret.written |= (abi->getCallWrittenRegisters());
545     }
546     break;
547   default:
548     {
549       bool isInterrupt = false;
550       bool isSyscall = false;
551
552
553       if ((curInsn.getOperation().getID() == e_int) ||
554           (curInsn.getOperation().getID() == e_int3)) {
555         isInterrupt = true;
556       }
557       static RegisterAST::Ptr gs(new RegisterAST(x86::gs));
558       if (((curInsn.getOperation().getID() == e_call) &&
559            /*(curInsn()->getOperation().isRead(gs))) ||*/
560            (curInsn.getOperand(0).format(curInsn.getArch()) == "16")) ||
561           (curInsn.getOperation().getID() == e_syscall) ||
562           (curInsn.getOperation().getID() == e_int) ||
563           (curInsn.getOperation().getID() == power_op_sc)) {
564         isSyscall = true;
565       }
566
567       if (curInsn.getOperation().getID() == power_op_svcs) {
568         isSyscall = true;
569       }
570       if (curInsn.getOperation().getID() == aarch64_op_svc) {
571           isSyscall = true;
572       }
573       if (isInterrupt || isSyscall) {
574         ret.read |= (abi->getSyscallReadRegisters());
575         ret.written |= (abi->getSyscallWrittenRegisters());
576       }
577     }
578     break;
579   }       
580   return ret;
581 }
582
583 void *LivenessAnalyzer::getPtrToInstruction(Block *block, Address addr) const{
584
585         if (addr < block->start()) return NULL;
586         if (addr > block->end()) return NULL;
587         return block->region()->getPtrToInstruction(addr);
588 }
589 bool LivenessAnalyzer::isExitBlock(Block *block)
590 {
591     boost::lock_guard<Block> g(*block);
592     const Block::edgelist & trgs = block->targets();
593
594     bool interprocEdge = false;
595     bool intraprocEdge = false;
596     for (Block::edgelist::const_iterator eit=trgs.begin(); eit != trgs.end(); ++eit){
597         if ((*eit)->type() == CATCH) continue;
598         if ((*eit)->interproc()) interprocEdge = true; else intraprocEdge = true;
599     }
600
601     if (interprocEdge && !intraprocEdge) return true; else return false;
602 }
603
604 void LivenessAnalyzer::clean(){
605
606         blockLiveInfo.clear();
607         liveFuncCalculated.clear();
608         cachedLivenessInfo.clean();
609 }
610
611 void LivenessAnalyzer::clean(Function *func){
612
613         if (liveFuncCalculated.find(func) != liveFuncCalculated.end()){         
614                 liveFuncCalculated.erase(func);
615                 Function::blocklist::iterator sit = func->blocks().begin();
616                 for( ; sit != func->blocks().end(); sit++) {
617                         blockLiveInfo.erase(*sit);
618                 }
619
620         }
621         if (cachedLivenessInfo.getCurFunc() == func) cachedLivenessInfo.clean();
622
623 }
624
625 bool LivenessAnalyzer::isMMX(MachRegister machReg){
626         if ((machReg.val() & Arch_x86) == Arch_x86 || (machReg.val() & Arch_x86_64) == Arch_x86_64){
627                 assert( ((machReg.val() & x86::MMX) == x86::MMX) == ((machReg.val() & x86_64::MMX) == x86_64::MMX) );
628                 return (machReg.val() & x86::MMX) == x86::MMX;
629         }
630         return false;
631 }
632
633 MachRegister LivenessAnalyzer::changeIfMMX(MachRegister machReg){
634         if (!isMMX(machReg)) return machReg;
635         if (width == 4) return x86::mm0; else return x86_64::mm0;
636 }