From vadve at cs.uiuc.edu Mon Dec 9 18:43:01 2002 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon Dec 9 18:43:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Parallelize.h Message-ID: <200212100042.SAA19452@psmith.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms: Parallelize.h added (r1.1) --- Log message: The pass Parallelize automatically parallelizes a program using the Cilk multi-threaded runtime system to execute parallel code. This file exposes some routines needed for code generation for that pass. --- Diffs of the changes: From vadve at cs.uiuc.edu Mon Dec 9 18:44:01 2002 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon Dec 9 18:44:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/Parallelize.cpp Message-ID: <200212100043.SAA19464@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: Parallelize.cpp added (r1.1) --- Log message: This file implements a pass that automatically parallelizes a program, using the Cilk multi-threaded runtime system to execute parallel code. The current version inserts too many sync() operations in the program because it does not attempt to optimize their placement. --- Diffs of the changes: From vadve at cs.uiuc.edu Tue Dec 10 07:07:01 2002 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Tue Dec 10 07:07:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Support/Cilkifier.h Message-ID: <200212101306.HAA32448@niobe.cs.uiuc.edu> Changes in directory llvm/include/llvm/Support: Cilkifier.h added (r1.1) --- Log message: External routines used to identify Cilk operations inserted by the parallelization pass. --- Diffs of the changes: From vadve at cs.uiuc.edu Tue Dec 10 07:08:01 2002 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Tue Dec 10 07:08:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Utils/DemoteRegToStack.h Message-ID: <200212101307.HAA32466@niobe.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms/Utils: DemoteRegToStack.h added (r1.1) --- Log message: This file provides the function DemoteRegToStack(), which takes a virtual register computed by an Instruction& X and replaces it with a slot in the stack frame, allocated via alloca. --- Diffs of the changes: From vadve at cs.uiuc.edu Tue Dec 10 07:09:01 2002 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Tue Dec 10 07:09:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/DemoteRegToStack.cpp Message-ID: <200212101308.HAA32484@niobe.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: DemoteRegToStack.cpp added (r1.1) --- Log message: This file implements the function DemoteRegToStack(), which takes a virtual register computed by an Instruction& X and replaces it with a slot in the stack frame, allocated via alloca. --- Diffs of the changes: From vadve at cs.uiuc.edu Tue Dec 10 07:09:03 2002 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Tue Dec 10 07:09:03 2002 Subject: [llvm-commits] CVS: llvm/lib/Support/Cilkifier.cpp Message-ID: <200212101308.HAA32497@niobe.cs.uiuc.edu> Changes in directory llvm/lib/Support: Cilkifier.cpp added (r1.1) --- Log message: External routines used to identify Cilk operations inserted by the parallelization pass. --- Diffs of the changes: From lattner at cs.uiuc.edu Wed Dec 11 21:44:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Dec 11 21:44:01 2002 Subject: [llvm-commits] CVS: llvm/include/Support/Signals.h Message-ID: <200212120343.VAA09311@apoc.cs.uiuc.edu> Changes in directory llvm/include/Support: Signals.h updated: 1.1 -> 1.2 --- Log message: Fix header --- Diffs of the changes: Index: llvm/include/Support/Signals.h diff -u llvm/include/Support/Signals.h:1.1 llvm/include/Support/Signals.h:1.2 --- llvm/include/Support/Signals.h:1.1 Thu Apr 18 14:53:34 2002 +++ llvm/include/Support/Signals.h Wed Dec 11 21:43:30 2002 @@ -1,4 +1,4 @@ -//===- Support/Signals.h - Signal Handling support ---------------*- C++ -*--=// +//===- Support/Signals.h - Signal Handling support -------------*- C++ -*-===// // // This file defines some helpful functions for dealing with the possibility of // unix signals occuring while your program is running. @@ -16,3 +16,4 @@ void RemoveFileOnSignal(const std::string &Filename); #endif + From lattner at cs.uiuc.edu Wed Dec 11 21:45:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Dec 11 21:45:01 2002 Subject: [llvm-commits] CVS: llvm/utils/getsrcs.sh Message-ID: <200212120344.VAA09326@apoc.cs.uiuc.edu> Changes in directory llvm/utils: getsrcs.sh updated: 1.7 -> 1.8 --- Log message: Include tablegen --- Diffs of the changes: Index: llvm/utils/getsrcs.sh diff -u llvm/utils/getsrcs.sh:1.7 llvm/utils/getsrcs.sh:1.8 --- llvm/utils/getsrcs.sh:1.7 Fri Sep 6 16:04:36 2002 +++ llvm/utils/getsrcs.sh Wed Dec 11 21:44:42 2002 @@ -1,5 +1,5 @@ #!/bin/sh # This is useful because it prints out all of the source files. Useful for # greps. -find www include lib tools -name \*.\[cdhyl\]\* | grep -v Lexer.cpp | grep -v llvmAsmParser.cpp | grep -v llvmAsmParser.h | grep -v '~$' | grep -v '\.ll$' | grep -v .flc | grep -v Sparc.burm.c | grep -v '\.d$' | grep -v '\.dir$' | grep -v www/docs/doxygen | grep -v include/boost +find www include lib tools utils -name \*.\[cdhyl\]\* | grep -v Lexer.cpp | grep -v llvmAsmParser.cpp | grep -v llvmAsmParser.h | grep -v '~$' | grep -v '\.ll$' | grep -v .flc | grep -v Sparc.burm.c | grep -v '\.d$' | grep -v '\.dir$' | grep -v www/docs/doxygen | grep -v include/boost | grep -v /Burg/ From lattner at cs.uiuc.edu Wed Dec 11 21:48:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Dec 11 21:48:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DependenceGraph.cpp Message-ID: <200212120347.VAA09391@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: DependenceGraph.cpp updated: 1.1 -> 1.2 --- Log message: Remove #includes --- Diffs of the changes: Index: llvm/lib/Analysis/DependenceGraph.cpp diff -u llvm/lib/Analysis/DependenceGraph.cpp:1.1 llvm/lib/Analysis/DependenceGraph.cpp:1.2 --- llvm/lib/Analysis/DependenceGraph.cpp:1.1 Sun Dec 8 07:26:29 2002 +++ llvm/lib/Analysis/DependenceGraph.cpp Wed Dec 11 21:47:27 2002 @@ -16,8 +16,6 @@ #include "llvm/Analysis/DependenceGraph.h" #include "llvm/Function.h" -#include "llvm/BasicBlock.h" -#include "llvm/Instruction.h" //---------------------------------------------------------------------------- From brukman at cs.uiuc.edu Wed Dec 11 23:29:00 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed Dec 11 23:29:00 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/DataStructure.h Message-ID: <200212120528.XAA13874@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: DataStructure.h updated: 1.59 -> 1.60 --- Log message: No need to specify the class if the method is within the class declaration. --- Diffs of the changes: Index: llvm/include/llvm/Analysis/DataStructure.h diff -u llvm/include/llvm/Analysis/DataStructure.h:1.59 llvm/include/llvm/Analysis/DataStructure.h:1.60 --- llvm/include/llvm/Analysis/DataStructure.h:1.59 Tue Nov 12 09:57:28 2002 +++ llvm/include/llvm/Analysis/DataStructure.h Wed Dec 11 23:28:39 2002 @@ -109,8 +109,8 @@ // outside of the SCC) into functions in the SCC. It is not supposed to touch // functions IN the SCC at all. // - DSGraph &BUDataStructures::inlineNonSCCGraphs(Function &F, - std::set &SCCFunctions); + DSGraph &inlineNonSCCGraphs(Function &F, + std::set &SCCFunctions); DSGraph &calculateSCCGraph(Function &F, std::set &InlinedSCCFunctions); From brukman at cs.uiuc.edu Wed Dec 11 23:30:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed Dec 11 23:30:01 2002 Subject: [llvm-commits] CVS: llvm/tools/opt/Makefile Message-ID: <200212120529.XAA13891@apoc.cs.uiuc.edu> Changes in directory llvm/tools/opt: Makefile updated: 1.37 -> 1.38 --- Log message: ipa.a only needs to be mentioned once, and spaces should be used instead of tabs for readability. --- Diffs of the changes: Index: llvm/tools/opt/Makefile diff -u llvm/tools/opt/Makefile:1.37 llvm/tools/opt/Makefile:1.38 --- llvm/tools/opt/Makefile:1.37 Sun Dec 8 22:46:25 2002 +++ llvm/tools/opt/Makefile Wed Dec 11 23:29:32 2002 @@ -2,14 +2,11 @@ TOOLNAME = opt USEDLIBS = bcreader bcwriter instrument profpaths \ - sparc mapping regalloc.a sched select codegen preopts \ - postopts.a \ - livevar scalaropts \ - ipo ipa.a datastructure transforms target.a analysis ipa.a \ + sparc mapping regalloc.a sched select codegen preopts \ + postopts.a livevar scalaropts \ + ipo ipa.a datastructure transforms target.a analysis \ transformutils vmcore support TOOLLINKOPTS = -ldl -KEEP_SYMBOLS = 1 include $(LEVEL)/Makefile.common - From lattner at cs.uiuc.edu Wed Dec 11 23:32:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Dec 11 23:32:00 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/DependenceGraph.h Message-ID: <200212120531.XAA13948@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: DependenceGraph.h updated: 1.1 -> 1.2 --- Log message: Make a release build compile. This field is not really an enum, it's really a bitfield --- Diffs of the changes: Index: llvm/include/llvm/Analysis/DependenceGraph.h diff -u llvm/include/llvm/Analysis/DependenceGraph.h:1.1 llvm/include/llvm/Analysis/DependenceGraph.h:1.2 --- llvm/include/llvm/Analysis/DependenceGraph.h:1.1 Sun Dec 8 07:26:04 2002 +++ llvm/include/llvm/Analysis/DependenceGraph.h Wed Dec 11 23:31:26 2002 @@ -59,7 +59,7 @@ class Dependence { DepGraphNode* toOrFromNode; - DependenceType depType:8; + unsigned char depType; public: /*ctor*/ Dependence (DepGraphNode* toOrFromN, @@ -78,7 +78,7 @@ /// Get information about the type of dependence. /// - DependenceType getDepType() { + unsigned getDepType() const { return depType; } From brukman at cs.uiuc.edu Wed Dec 11 23:35:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed Dec 11 23:35:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DataStructure/Steensgaard.cpp Message-ID: <200212120534.XAA14030@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/DataStructure: Steensgaard.cpp updated: 1.13 -> 1.14 --- Log message: 'graph' is spelled without a 'c'. Also added Statistic counters for NoAlias and MayAlias. --- Diffs of the changes: Index: llvm/lib/Analysis/DataStructure/Steensgaard.cpp diff -u llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.13 llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.14 --- llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.13 Sat Nov 9 16:06:59 2002 +++ llvm/lib/Analysis/DataStructure/Steensgaard.cpp Wed Dec 11 23:34:10 2002 @@ -14,6 +14,11 @@ #include "Support/Statistic.h" namespace { + Statistic<> NumNoAlias ("steens", "Number of 'no alias' replies"); + Statistic<> NumMayAlias ("steens", "Number of 'may alias' replies"); +}; + +namespace { class Steens : public Pass, public AliasAnalysis { DSGraph *ResultGraph; public: @@ -202,7 +207,7 @@ // alias - This is the only method here that does anything interesting... AliasAnalysis::Result Steens::alias(const Value *V1, const Value *V2) { - assert(ResultGraph && "Result grcaph has not yet been computed!"); + assert(ResultGraph && "Result graph has not been computed yet!"); std::map &GVM = ResultGraph->getScalarMap(); @@ -214,9 +219,10 @@ DSNodeHandle &V2H = J->second; // If the two pointers point to different data structure graph nodes, they // cannot alias! - if (V1H.getNode() != V2H.getNode()) + if (V1H.getNode() != V2H.getNode()) { + ++NumNoAlias; return NoAlias; - + } // FIXME: If the two pointers point to the same node, and the offsets are // different, and the LinkIndex vector doesn't alias the section, then the // two pointers do not alias. We need access size information for the two @@ -224,6 +230,9 @@ // } } + + // Since Steensgaard cannot do any better, count it as a 'may alias' + ++NumMayAlias; // If we cannot determine alias properties based on our graph, fall back on // some other AA implementation. From lattner at cs.uiuc.edu Thu Dec 12 09:34:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 09:34:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp X86InstrInfo.def Message-ID: <200212121533.JAA12809@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.53 -> 1.54 X86InstrInfo.def updated: 1.34 -> 1.35 --- Log message: This checkin is brought to you by the brian gaeke allnighter fund. (lib/Target/X86) InstSelectSimple.cpp: Include llvm/DerivedTypes.h and iostream. Refactor visitMul out into a wrapper around doMultiply(), so that we can do multiplications on temporary values when we are doing getelementptrs. Refactor part of getReg out into makeAnotherReg, so that we can create registers willy-nilly to hold temporary values, when we are doing getelementptrs. Add stub implementations of visitMallocInst and visitAllocaInst. Add initial implementation of visitGetElementPtrInst. In copyConstantToRegister: We throw a *lot* of our asserts here. So, when we want to throw an assert, print out to stderr whatever expr or whatever constant made us barf. Support copying ConstantPointerNull to register, using a move immediate of zero. Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings of the numbers in the other instruction names. All uses modified. Teach visitCallInst to extract byte- and short-class return values from subregs of EAX. Add a FIXME note about how we would do it for float-class return values. Add a FIXME note about how we would cast float to int and back. X86InstrInfo.def: Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings of the numbers in the other instruction names. All uses modified. (tools/jello) GlobalVars.cpp: Include iostream. If we have to emit a floating-point constant to memory, gamble and use the same method as for ints. If we have to emit a ConstantPointerNull to memory, try using a "void *" and "NULL". Otherwise, if we are going to throw an assert, print out whatever constant made us barf, first. --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.53 llvm/lib/Target/X86/InstSelectSimple.cpp:1.54 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.53 Fri Dec 6 04:49:33 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Thu Dec 12 09:33:39 2002 @@ -14,6 +14,7 @@ #include "llvm/iPHINode.h" #include "llvm/iMemory.h" #include "llvm/Type.h" +#include "llvm/DerivedTypes.h" #include "llvm/Constants.h" #include "llvm/Pass.h" #include "llvm/CodeGen/MachineFunction.h" @@ -22,6 +23,7 @@ #include "llvm/Support/InstVisitor.h" #include "llvm/Target/MRegisterInfo.h" #include +#include using namespace MOTy; // Get Use, Def, UseAndDef @@ -73,6 +75,8 @@ void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass); void visitAdd(BinaryOperator &B) { visitSimpleBinary(B, 0); } void visitSub(BinaryOperator &B) { visitSimpleBinary(B, 1); } + void doMultiply(unsigned destReg, const Type *resultType, + unsigned op0Reg, unsigned op1Reg); void visitMul(BinaryOperator &B); void visitDiv(BinaryOperator &B) { visitDivRem(B); } @@ -96,7 +100,10 @@ // Memory Instructions void visitLoadInst(LoadInst &I); void visitStoreInst(StoreInst &I); - + void visitGetElementPtrInst(GetElementPtrInst &I); + void visitMallocInst(MallocInst &I); + void visitAllocaInst(AllocaInst &I); + // Other operators void visitShiftInst(ShiftInst &I); void visitPHINode(PHINode &I); @@ -114,6 +121,13 @@ /// void copyConstantToRegister(Constant *C, unsigned Reg); + /// makeAnotherReg - This method returns the next register number + /// we haven't yet used. + unsigned makeAnotherReg (void) { + unsigned Reg = CurReg++; + return Reg; + } + /// getReg - This method turns an LLVM value into a register number. This /// is guaranteed to produce the same register number for a particular value /// every time it is queried. @@ -122,7 +136,7 @@ unsigned getReg(Value *V) { unsigned &Reg = RegMap[V]; if (Reg == 0) { - Reg = CurReg++; + Reg = makeAnotherReg (); RegMap[V] = Reg; // Add the mapping of regnumber => reg class to MachineFunction @@ -182,6 +196,11 @@ /// specified constant into the specified register. /// void ISel::copyConstantToRegister(Constant *C, unsigned R) { + if (isa (C)) { + // FIXME: We really need to handle getelementptr exprs, among + // other things. + std::cerr << "Offending expr: " << C << "\n"; + } assert (!isa(C) && "Constant expressions not yet handled!\n"); if (C->getType()->isIntegral()) { @@ -199,7 +218,11 @@ ConstantUInt *CUI = cast(C); BuildMI(BB, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue()); } + } else if (isa (C)) { + // Copy zero (null pointer) to the register. + BuildMI (BB, X86::MOVir32, 1, R).addZImm(0); } else { + std::cerr << "Offending constant: " << C << "\n"; assert(0 && "Type not handled yet!"); } } @@ -236,12 +259,12 @@ // FIXME: assuming var1, var2 are in memory, if not, spill to // stack first case cFloat: // Floats - BuildMI (BB, X86::FLDr4, 1).addReg (reg1); - BuildMI (BB, X86::FLDr4, 1).addReg (reg2); + BuildMI (BB, X86::FLDr32, 1).addReg (reg1); + BuildMI (BB, X86::FLDr32, 1).addReg (reg2); break; case cDouble: // Doubles - BuildMI (BB, X86::FLDr8, 1).addReg (reg1); - BuildMI (BB, X86::FLDr8, 1).addReg (reg2); + BuildMI (BB, X86::FLDr64, 1).addReg (reg1); + BuildMI (BB, X86::FLDr64, 1).addReg (reg2); break; case cLong: default: @@ -345,10 +368,10 @@ // ret float/double: top of FP stack // FLD case cFloat: // Floats - BuildMI (BB, X86::FLDr4, 1).addReg (getReg (rv)); + BuildMI (BB, X86::FLDr32, 1).addReg (getReg (rv)); break; case cDouble: // Doubles - BuildMI (BB, X86::FLDr8, 1).addReg (getReg (rv)); + BuildMI (BB, X86::FLDr64, 1).addReg (getReg (rv)); break; case cLong: // ret long: use EAX(least significant 32 bits)/EDX (most @@ -435,11 +458,31 @@ // leaves it in... // if (CI.getType() != Type::VoidTy) { - switch (getClass(CI.getType())) { - case cInt: - BuildMI(BB, X86::MOVrr32, 1, getReg(CI)).addReg(X86::EAX); + unsigned resultTypeClass = getClass (CI.getType ()); + switch (resultTypeClass) { + case cByte: + case cShort: + case cInt: { + // Integral results are in %eax, or the appropriate portion + // thereof. + static const unsigned regRegMove[] = { + X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 + }; + static const unsigned AReg[] = { X86::AL, X86::AX, X86::EAX }; + BuildMI (BB, regRegMove[resultTypeClass], 1, + getReg (CI)).addReg (AReg[resultTypeClass]); + break; + } + case cFloat: + // Floating-point return values live in %st(0) (i.e., the top of + // the FP stack.) The general way to approach this is to do a + // FSTP to save the top of the FP stack on the real stack, then + // do a MOV to load the top of the real stack into the target + // register. + visitInstruction (CI); // FIXME: add the right args for the calls below + // BuildMI (BB, X86::FSTPm32, 0); + // BuildMI (BB, X86::MOVmr32, 0); break; - default: std::cerr << "Cannot get return value for call of type '" << *CI.getType() << "'\n"; @@ -477,30 +520,41 @@ BuildMI(BB, Opcode, 2, getReg(B)).addReg(Op0r).addReg(Op1r); } -/// visitMul - Multiplies are not simple binary operators because they must deal -/// with the EAX register explicitly. -/// -void ISel::visitMul(BinaryOperator &I) { - unsigned Class = getClass(I.getType()); - if (Class > 2) // FIXME: Handle longs - visitInstruction(I); +/// doMultiply - Emit appropriate instructions to multiply together +/// the registers op0Reg and op1Reg, and put the result in destReg. +/// The type of the result should be given as resultType. +void +ISel::doMultiply(unsigned destReg, const Type *resultType, + unsigned op0Reg, unsigned op1Reg) +{ + unsigned Class = getClass (resultType); + // FIXME: + assert (Class <= 2 && "Someday, we will learn how to multiply" + "longs and floating-point numbers. This is not that day."); + static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX }; static const unsigned MulOpcode[]={ X86::MULrr8, X86::MULrr16, X86::MULrr32 }; static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 }; - unsigned Reg = Regs[Class]; - unsigned Op0Reg = getReg(I.getOperand(0)); - unsigned Op1Reg = getReg(I.getOperand(1)); - // Put the first operand into one of the A registers... - BuildMI(BB, MovOpcode[Class], 1, Reg).addReg(Op0Reg); + // Emit a MOV to put the first operand into the appropriately-sized + // subreg of EAX. + BuildMI (BB, MovOpcode[Class], 1, Reg).addReg (op0Reg); - // Emit the appropriate multiply instruction... - BuildMI(BB, MulOpcode[Class], 1).addReg(Op1Reg); + // Emit the appropriate multiply instruction. + BuildMI (BB, MulOpcode[Class], 1).addReg (op1Reg); - // Put the result into the destination register... - BuildMI(BB, MovOpcode[Class], 1, getReg(I)).addReg(Reg); + // Emit another MOV to put the result into the destination register. + BuildMI (BB, MovOpcode[Class], 1, destReg).addReg (Reg); +} + +/// visitMul - Multiplies are not simple binary operators because they must deal +/// with the EAX register explicitly. +/// +void ISel::visitMul(BinaryOperator &I) { + doMultiply (getReg (I), I.getType (), + getReg (I.getOperand (0)), getReg (I.getOperand (1))); } @@ -732,8 +786,118 @@ return; } // Anything we haven't handled already, we can't (yet) handle at all. + // + // FP to integral casts can be handled with FISTP to store onto the + // stack while converting to integer, followed by a MOV to load from + // the stack into the result register. Integral to FP casts can be + // handled with MOV to store onto the stack, followed by a FILD to + // load from the stack while converting to FP. For the moment, I + // can't quite get straight in my head how to borrow myself some + // stack space and write on it. Otherwise, this would be trivial. visitInstruction (CI); } + +/// visitGetElementPtrInst - I don't know, most programs don't have +/// getelementptr instructions, right? That means we can put off +/// implementing this, right? Right. This method emits machine +/// instructions to perform type-safe pointer arithmetic. I am +/// guessing this could be cleaned up somewhat to use fewer temporary +/// registers. +void +ISel::visitGetElementPtrInst (GetElementPtrInst &I) +{ + Value *basePtr = I.getPointerOperand (); + const TargetData &TD = TM.DataLayout; + unsigned basePtrReg = getReg (basePtr); + unsigned resultReg = getReg (I); + const Type *Ty = basePtr->getType(); + // GEPs have zero or more indices; we must perform a struct access + // or array access for each one. + for (GetElementPtrInst::op_iterator oi = I.idx_begin (), + oe = I.idx_end (); oi != oe; ++oi) { + Value *idx = *oi; + unsigned nextBasePtrReg = makeAnotherReg (); + if (const StructType *StTy = dyn_cast (Ty)) { + // It's a struct access. idx is the index into the structure, + // which names the field. This index must have ubyte type. + const ConstantUInt *CUI = cast (idx); + assert (CUI->getType () == Type::UByteTy + && "Funny-looking structure index in GEP"); + // Use the TargetData structure to pick out what the layout of + // the structure is in memory. Since the structure index must + // be constant, we can get its value and use it to find the + // right byte offset from the StructLayout class's list of + // structure member offsets. + unsigned idxValue = CUI->getValue (); + unsigned memberOffset = + TD.getStructLayout (StTy)->MemberOffsets[idxValue]; + // Emit an ADD to add memberOffset to the basePtr. + BuildMI (BB, X86::ADDri32, 2, + nextBasePtrReg).addReg (basePtrReg).addZImm (memberOffset); + // The next type is the member of the structure selected by the + // index. + Ty = StTy->getElementTypes ()[idxValue]; + } else if (const SequentialType *SqTy = cast (Ty)) { + // It's an array or pointer access: [ArraySize x ElementType]. + // The documentation does not seem to match the code on the type + // of array indices. The code seems to use long, and the docs + // (and the comments) say uint. If it is long, I don't know what + // we are going to do, because the X86 loves 64-bit types. + const Type *typeOfSequentialTypeIndex = SqTy->getIndexType (); + // idx is the index into the array. Unlike with structure + // indices, we may not know its actual value at code-generation + // time. + assert (idx->getType () == typeOfSequentialTypeIndex + && "Funny-looking array index in GEP"); + // We want to add basePtrReg to (idxReg * sizeof + // ElementType). First, we must find the size of the pointed-to + // type. (Not coincidentally, the next type is the type of the + // elements in the array.) + Ty = SqTy->getElementType (); + unsigned elementSize = TD.getTypeSize (Ty); + unsigned elementSizeReg = makeAnotherReg (); + copyConstantToRegister (ConstantInt::get (typeOfSequentialTypeIndex, + elementSize), + elementSizeReg); + unsigned idxReg = getReg (idx); + // Emit a MUL to multiply the register holding the index by + // elementSize, putting the result in memberOffsetReg. + unsigned memberOffsetReg = makeAnotherReg (); + doMultiply (memberOffsetReg, typeOfSequentialTypeIndex, + elementSizeReg, idxReg); + // Emit an ADD to add memberOffsetReg to the basePtr. + BuildMI (BB, X86::ADDrr32, 2, + nextBasePtrReg).addReg (basePtrReg).addReg (memberOffsetReg); + } + // Now that we are here, further indices refer to subtypes of this + // one, so we don't need to worry about basePtrReg itself, anymore. + basePtrReg = nextBasePtrReg; + } + // After we have processed all the indices, the result is left in + // basePtrReg. Move it to the register where we were expected to + // put the answer. A 32-bit move should do it, because we are in + // ILP32 land. + BuildMI (BB, X86::MOVrr32, 1, getReg (I)).addReg (basePtrReg); +} + + +/// visitMallocInst - I know that personally, whenever I want to remember +/// something, I have to clear off some space in my brain. +void +ISel::visitMallocInst (MallocInst &I) +{ + visitInstruction (I); +} + + +/// visitAllocaInst - I want some stack space. Come on, man, I said I +/// want some freakin' stack space. +void +ISel::visitAllocaInst (AllocaInst &I) +{ + visitInstruction (I); +} + /// createSimpleX86InstructionSelector - This pass converts an LLVM function /// into a machine code representation is a very simple peep-hole fashion. The Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.34 llvm/lib/Target/X86/X86InstrInfo.def:1.35 --- llvm/lib/Target/X86/X86InstrInfo.def:1.34 Thu Dec 5 02:30:40 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Thu Dec 12 09:33:39 2002 @@ -152,8 +152,8 @@ I(SARir32 , "sarl", 0xC1, 0, X86II::MRMS7r, NoIR, NoIR) // R32 >>= imm8 // Floating point loads -I(FLDr4 , "flds", 0xD9, 0, X86II::MRMS0m, NoIR, NoIR) // push float -I(FLDr8 , "fldl ", 0xDD, 0, X86II::MRMS0m, NoIR, NoIR) // push double +I(FLDr32 , "flds", 0xD9, 0, X86II::MRMS0m, NoIR, NoIR) // push float +I(FLDr64 , "fldl", 0xDD, 0, X86II::MRMS0m, NoIR, NoIR) // push double // Floating point compares I(FUCOMPP , "fucompp", 0xDA, 0, X86II::Void, NoIR, NoIR) // compare+pop2x From lattner at cs.uiuc.edu Thu Dec 12 09:34:03 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 09:34:03 2002 Subject: [llvm-commits] CVS: llvm/tools/jello/GlobalVars.cpp Message-ID: <200212121533.JAA12806@psmith.cs.uiuc.edu> Changes in directory llvm/tools/jello: GlobalVars.cpp updated: 1.1 -> 1.2 --- Log message: This checkin is brought to you by the brian gaeke allnighter fund. (lib/Target/X86) InstSelectSimple.cpp: Include llvm/DerivedTypes.h and iostream. Refactor visitMul out into a wrapper around doMultiply(), so that we can do multiplications on temporary values when we are doing getelementptrs. Refactor part of getReg out into makeAnotherReg, so that we can create registers willy-nilly to hold temporary values, when we are doing getelementptrs. Add stub implementations of visitMallocInst and visitAllocaInst. Add initial implementation of visitGetElementPtrInst. In copyConstantToRegister: We throw a *lot* of our asserts here. So, when we want to throw an assert, print out to stderr whatever expr or whatever constant made us barf. Support copying ConstantPointerNull to register, using a move immediate of zero. Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings of the numbers in the other instruction names. All uses modified. Teach visitCallInst to extract byte- and short-class return values from subregs of EAX. Add a FIXME note about how we would do it for float-class return values. Add a FIXME note about how we would cast float to int and back. X86InstrInfo.def: Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings of the numbers in the other instruction names. All uses modified. (tools/jello) GlobalVars.cpp: Include iostream. If we have to emit a floating-point constant to memory, gamble and use the same method as for ints. If we have to emit a ConstantPointerNull to memory, try using a "void *" and "NULL". Otherwise, if we are going to throw an assert, print out whatever constant made us barf, first. --- Diffs of the changes: Index: llvm/tools/jello/GlobalVars.cpp diff -u llvm/tools/jello/GlobalVars.cpp:1.1 llvm/tools/jello/GlobalVars.cpp:1.2 --- llvm/tools/jello/GlobalVars.cpp:1.1 Wed Dec 4 00:09:04 2002 +++ llvm/tools/jello/GlobalVars.cpp Thu Dec 12 09:33:40 2002 @@ -9,6 +9,7 @@ #include "llvm/Constants.h" #include "llvm/Target/TargetMachine.h" #include "VM.h" +#include /// EmitGlobals - Emit all of the global variables to memory, storing their /// addresses into GlobalAddress. This must make sure to copy the contents of @@ -77,6 +78,20 @@ return; default: break; } + } else if (ConstantFP *CF = dyn_cast (Init)) { + switch (CF->getType ()->getPrimitiveID ()) { + case Type::FloatTyID: + *(float*)Addr = CF->getValue (); + return; + case Type::DoubleTyID: + *(double*)Addr = CF->getValue (); + return; + default: break; + } + } else if (ConstantPointerNull *CP = dyn_cast (Init)) { + // Fill the space with a NULL pointer. + *(void **)Addr = NULL; + return; } else if (ConstantArray *CA = dyn_cast(Init)) { unsigned ElementSize = TD.getTypeSize(CA->getType()->getElementType()); for (unsigned i = 0, e = CA->getType()->getNumElements(); i != e; ++i) { @@ -86,5 +101,6 @@ return; } + std::cerr << "Offending constant: " << Init << "\n"; assert(0 && "Don't know how to emit this constant to memory!"); } From brukman at cs.uiuc.edu Thu Dec 12 17:20:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Dec 12 17:20:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.def Message-ID: <200212122319.RAA22699@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.def updated: 1.35 -> 1.36 --- Log message: Added the flag to mark instructions which are really 2-address instructions in X86, but would be 3-address in any normail architecture. --- Diffs of the changes: Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.35 llvm/lib/Target/X86/X86InstrInfo.def:1.36 --- llvm/lib/Target/X86/X86InstrInfo.def:1.35 Thu Dec 12 09:33:39 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Thu Dec 12 17:19:11 2002 @@ -93,14 +93,14 @@ I(POPr32 , "popl", 0x58, 0, X86II::AddRegFrm, NoIR, NoIR) // Arithmetic instructions -I(ADDrr8 , "addb", 0x00, 0, X86II::MRMDestReg, NoIR, NoIR) // R8 += R8 -I(ADDrr16 , "addw", 0x01, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 += R16 -I(ADDrr32 , "addl", 0x01, 0, X86II::MRMDestReg, NoIR, NoIR) // R32 += R32 -I(ADDri32 , "add", 0x81, 0, X86II::MRMS0r, NoIR, NoIR) // R32 += imm32 -I(SUBrr8 , "subb", 0x2A, 0, X86II::MRMDestReg, NoIR, NoIR) // R8 -= R8 -I(SUBrr16 , "subw", 0x2B, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 -= R16 -I(SUBrr32 , "subl", 0x2B, 0, X86II::MRMDestReg, NoIR, NoIR) // R32 -= R32 -I(SUBri32 , "sub", 0x81, 0, X86II::MRMS5r, NoIR, NoIR) // R32 -= imm32 +I(ADDrr8 , "addb", 0x00, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 += R8 +I(ADDrr16 , "addw", 0x01, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 += R16 +I(ADDrr32 , "addl", 0x01, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 += R32 +I(ADDri32 , "add", 0x81, M_2_ADDR_FLAG, X86II::MRMS0r, NoIR, NoIR) // R32 += imm32 +I(SUBrr8 , "subb", 0x2A, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 -= R8 +I(SUBrr16 , "subw", 0x2B, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 -= R16 +I(SUBrr32 , "subl", 0x2B, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 -= R32 +I(SUBri32 , "sub", 0x81, M_2_ADDR_FLAG, X86II::MRMS5r, NoIR, NoIR) // R32 -= imm32 I(MULrr8 , "mulb", 0xF6, 0, X86II::MRMS4r | X86II::Void, O_AL, O_AX) // AX = AL*R8 I(MULrr16 , "mulw", 0xF7, 0, X86II::MRMS4r | X86II::Void | // DX:AX= AX*R16 X86II::OpSize, O_AX, T_AXDX) @@ -121,35 +121,35 @@ T_EAXEDX) // DA/r32=EAX&DX // Logical operators -I(ANDrr8 , "andb", 0x20, 0, X86II::MRMDestReg, NoIR, NoIR) // R8 &= R8 -I(ANDrr16 , "andw", 0x21, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 &= R16 -I(ANDrr32 , "andl", 0x21, 0, X86II::MRMDestReg, NoIR, NoIR) // R32 &= R32 -I(ORrr8 , "orb", 0x08, 0, X86II::MRMDestReg, NoIR, NoIR) // R8 |= R8 -I(ORrr16 , "orw", 0x09, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 |= R16 -I(ORrr32 , "orl", 0x09, 0, X86II::MRMDestReg, NoIR, NoIR) // R32 |= R32 -I(XORrr8 , "xorb", 0x30, 0, X86II::MRMDestReg, NoIR, NoIR) // R8 ^= R8 -I(XORrr16 , "xorw", 0x31, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 ^= R16 -I(XORrr32 , "xorl", 0x31, 0, X86II::MRMDestReg, NoIR, NoIR) // R32 ^= R32 +I(ANDrr8 , "andb", 0x20, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 &= R8 +I(ANDrr16 , "andw", 0x21, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 &= R16 +I(ANDrr32 , "andl", 0x21, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 &= R32 +I(ORrr8 , "orb", 0x08, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 |= R8 +I(ORrr16 , "orw", 0x09, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 |= R16 +I(ORrr32 , "orl", 0x09, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 |= R32 +I(XORrr8 , "xorb", 0x30, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 ^= R8 +I(XORrr16 , "xorw", 0x31, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 ^= R16 +I(XORrr32 , "xorl", 0x31, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 ^= R32 // Shift instructions -I(SHLrr8 , "shlb", 0xD2, 0, X86II::MRMS4r, O_CL, NoIR) // R8 <<= cl -I(SHLrr16 , "shlw", 0xD3, 0, X86II::MRMS4r | X86II::OpSize, O_CL, NoIR) // R16 <<= cl -I(SHLrr32 , "shll", 0xD3, 0, X86II::MRMS4r, O_CL, NoIR) // R32 <<= cl -I(SHLir8 , "shlb", 0xC0, 0, X86II::MRMS4r, NoIR, NoIR) // R8 <<= imm8 -I(SHLir16 , "shlw", 0xC1, 0, X86II::MRMS4r | X86II::OpSize, NoIR, NoIR) // R16 <<= imm8 -I(SHLir32 , "shll", 0xC1, 0, X86II::MRMS4r, NoIR, NoIR) // R32 <<= imm8 -I(SHRrr8 , "shrb", 0xD2, 0, X86II::MRMS5r, O_CL, NoIR) // R8 >>>= cl -I(SHRrr16 , "shrw", 0xD3, 0, X86II::MRMS5r | X86II::OpSize, O_CL, NoIR) // R16 >>>= cl -I(SHRrr32 , "shrl", 0xD3, 0, X86II::MRMS5r, O_CL, NoIR) // R32 >>>= cl -I(SHRir8 , "shrb", 0xC0, 0, X86II::MRMS5r, NoIR, NoIR) // R8 >>>= imm8 -I(SHRir16 , "shrw", 0xC1, 0, X86II::MRMS5r | X86II::OpSize, NoIR, NoIR) // R16 >>>= imm8 -I(SHRir32 , "shrl", 0xC1, 0, X86II::MRMS5r, NoIR, NoIR) // R32 >>>= imm8 -I(SARrr8 , "sarb", 0xD2, 0, X86II::MRMS7r, O_CL, NoIR) // R8 >>= cl -I(SARrr16 , "sarw", 0xD3, 0, X86II::MRMS7r | X86II::OpSize, O_CL, NoIR) // R16 >>= cl -I(SARrr32 , "sarl", 0xD3, 0, X86II::MRMS7r, O_CL, NoIR) // R32 >>= cl -I(SARir8 , "sarb", 0xC0, 0, X86II::MRMS7r, NoIR, NoIR) // R8 >>= imm8 -I(SARir16 , "sarw", 0xC1, 0, X86II::MRMS7r | X86II::OpSize, NoIR, NoIR) // R16 >>= imm8 -I(SARir32 , "sarl", 0xC1, 0, X86II::MRMS7r, NoIR, NoIR) // R32 >>= imm8 +I(SHLrr8 , "shlb", 0xD2, M_2_ADDR_FLAG, X86II::MRMS4r, O_CL, NoIR) // R8 <<= cl +I(SHLrr16 , "shlw", 0xD3, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::OpSize, O_CL, NoIR) // R16 <<= cl +I(SHLrr32 , "shll", 0xD3, M_2_ADDR_FLAG, X86II::MRMS4r, O_CL, NoIR) // R32 <<= cl +I(SHLir8 , "shlb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS4r, NoIR, NoIR) // R8 <<= imm8 +I(SHLir16 , "shlw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::OpSize, NoIR, NoIR) // R16 <<= imm8 +I(SHLir32 , "shll", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r, NoIR, NoIR) // R32 <<= imm8 +I(SHRrr8 , "shrb", 0xD2, M_2_ADDR_FLAG, X86II::MRMS5r, O_CL, NoIR) // R8 >>>= cl +I(SHRrr16 , "shrw", 0xD3, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::OpSize, O_CL, NoIR) // R16 >>>= cl +I(SHRrr32 , "shrl", 0xD3, M_2_ADDR_FLAG, X86II::MRMS5r, O_CL, NoIR) // R32 >>>= cl +I(SHRir8 , "shrb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS5r, NoIR, NoIR) // R8 >>>= imm8 +I(SHRir16 , "shrw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::OpSize, NoIR, NoIR) // R16 >>>= imm8 +I(SHRir32 , "shrl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r, NoIR, NoIR) // R32 >>>= imm8 +I(SARrr8 , "sarb", 0xD2, M_2_ADDR_FLAG, X86II::MRMS7r, O_CL, NoIR) // R8 >>= cl +I(SARrr16 , "sarw", 0xD3, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::OpSize, O_CL, NoIR) // R16 >>= cl +I(SARrr32 , "sarl", 0xD3, M_2_ADDR_FLAG, X86II::MRMS7r, O_CL, NoIR) // R32 >>= cl +I(SARir8 , "sarb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS7r, NoIR, NoIR) // R8 >>= imm8 +I(SARir16 , "sarw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::OpSize, NoIR, NoIR) // R16 >>= imm8 +I(SARir32 , "sarl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r, NoIR, NoIR) // R32 >>= imm8 // Floating point loads I(FLDr32 , "flds", 0xD9, 0, X86II::MRMS0m, NoIR, NoIR) // push float From brukman at cs.uiuc.edu Thu Dec 12 17:21:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Dec 12 17:21:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212122320.RAA22729@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.5 -> 1.6 --- Log message: Take advantage of our knowledge of 2-address X86 instructions and register-allocated them appropriately. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.5 llvm/lib/CodeGen/RegAllocSimple.cpp:1.6 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.5 Wed Dec 4 17:58:08 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Thu Dec 12 17:20:31 2002 @@ -38,6 +38,9 @@ // Maps physical register to their register classes std::map PhysReg2RegClassMap; + + // Made to combat the incorrect allocation of r2 = add r1, r1 + std::map VirtReg2PhysRegMap; // Maps RegClass => which index we can take a register from. Since this is a // simple register allocator, when we need a register of a certain class, we @@ -225,17 +228,30 @@ DEBUG(std::cerr << "const\n"); } else if (op.isVirtualRegister()) { virtualReg = (unsigned) op.getAllocatedRegNum(); - // save register to stack if it's a def DEBUG(std::cerr << "op: " << op << "\n"); DEBUG(std::cerr << "\t inst[" << i << "]: "; MI->print(std::cerr, TM)); - if (op.opIsDef()) { - physReg = getFreeReg(virtualReg); - MachineBasicBlock::iterator J = I; - J = saveVirtRegToStack(++J, virtualReg, physReg); - I = --J; + + // make sure the same virtual register maps to the same physical + // register in any given instruction + if (VirtReg2PhysRegMap.find(virtualReg) != VirtReg2PhysRegMap.end()) { + physReg = VirtReg2PhysRegMap[virtualReg]; } else { - I = moveUseToReg(I, virtualReg, physReg); + if (op.opIsDef()) { + if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) { + // must be same register number as the first operand + // This maps a = b + c into b += c, and saves b into a's spot + physReg = (unsigned) MI->getOperand(1).getAllocatedRegNum(); + } else { + physReg = getFreeReg(virtualReg); + } + MachineBasicBlock::iterator J = I; + J = saveVirtRegToStack(++J, virtualReg, physReg); + I = --J; + } else { + I = moveUseToReg(I, virtualReg, physReg); + } + VirtReg2PhysRegMap[virtualReg] = physReg; } MI->SetMachineOperandReg(i, physReg); DEBUG(std::cerr << "virt: " << virtualReg << @@ -244,6 +260,7 @@ } clearAllRegs(); + VirtReg2PhysRegMap.clear(); } } From brukman at cs.uiuc.edu Thu Dec 12 17:21:02 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Dec 12 17:21:02 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MachineInstrInfo.h Message-ID: <200212122320.RAA22714@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MachineInstrInfo.h updated: 1.36 -> 1.37 --- Log message: Define the 2-address flag used by X86 instructions (add,sub,and,or,xor) that need to be declared as such. --- Diffs of the changes: Index: llvm/include/llvm/Target/MachineInstrInfo.h diff -u llvm/include/llvm/Target/MachineInstrInfo.h:1.36 llvm/include/llvm/Target/MachineInstrInfo.h:1.37 --- llvm/include/llvm/Target/MachineInstrInfo.h:1.36 Mon Dec 2 23:41:32 2002 +++ llvm/include/llvm/Target/MachineInstrInfo.h Thu Dec 12 17:19:51 2002 @@ -54,7 +54,8 @@ const unsigned M_STORE_FLAG = 1 << 12; const unsigned M_DUMMY_PHI_FLAG = 1 << 13; const unsigned M_PSEUDO_FLAG = 1 << 14; - +// 3-addr instructions which really work like 2-addr ones, eg. X86 add/sub +const unsigned M_2_ADDR_FLAG = 1 << 15; struct MachineInstrDescriptor { const char * Name; // Assembly language mnemonic for the opcode. @@ -185,6 +186,9 @@ } bool isPseudoInstr(const MachineOpCode opCode) const { return get(opCode).Flags & M_PSEUDO_FLAG; + } + bool isTwoAddrInstr(const MachineOpCode opCode) const { + return get(opCode).Flags & M_2_ADDR_FLAG; } // Check if an instruction can be issued before its operands are ready, From brukman at cs.uiuc.edu Thu Dec 12 20:14:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Dec 12 20:14:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/MachineCodeEmitter.cpp Message-ID: <200212130213.UAA26405@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: MachineCodeEmitter.cpp updated: 1.6 -> 1.7 --- Log message: This is supposed to provide correct size for datatypes. Supposedly. --- Diffs of the changes: Index: llvm/lib/Target/X86/MachineCodeEmitter.cpp diff -u llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.6 llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.7 --- llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.6 Wed Dec 4 11:32:52 2002 +++ llvm/lib/Target/X86/MachineCodeEmitter.cpp Thu Dec 12 20:13:15 2002 @@ -203,6 +203,24 @@ MO.getType() == MachineOperand::MO_UnextendedImmed; } +unsigned sizeOfPtr (const MachineInstrDescriptor &Desc) { + switch (Desc.TSFlags & X86II::MemArgMask) { + case X86II::MemArg8: return 1; + case X86II::MemArg16: return 2; + case X86II::MemArg32: return 4; + case X86II::MemArg64: return 8; + case X86II::MemArg80: return 10; + case X86II::MemArg128: return 16; + default: { + // FIXME: This should be an assert, but it is returning 4 because that was + // the former behavior and it's what was expected. Once the assumptions + // below are fixed, this can become an assert. + return 4; + } + } +} + + void Emitter::emitInstruction(MachineInstr &MI) { unsigned Opcode = MI.getOpcode(); const MachineInstrDescriptor &Desc = II.get(Opcode); @@ -224,7 +242,7 @@ case X86II::AddRegFrm: MCE.emitByte(BaseOpcode + getX86RegNum(MI.getOperand(0).getReg())); if (MI.getNumOperands() == 2) { - unsigned Size = 4; + unsigned Size = sizeOfPtr(Desc); if (Value *V = MI.getOperand(1).getVRegValueOrNull()) { assert(Size == 4 && "Don't know how to emit non-pointer values!"); MCE.emitGlobalAddress(cast(V)); @@ -262,7 +280,7 @@ (Desc.TSFlags & X86II::FormMask)-X86II::MRMS0r); if (isImmediate(MI.getOperand(MI.getNumOperands()-1))) { - unsigned Size = 4; + unsigned Size = sizeOfPtr(Desc); emitConstant(MI.getOperand(MI.getNumOperands()-1).getImmedValue(), Size); } break; From lattner at cs.uiuc.edu Thu Dec 12 21:51:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 21:51:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/MachineCodeEmitter.cpp X86InstrInfo.def Message-ID: <200212130350.VAA26743@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: MachineCodeEmitter.cpp updated: 1.7 -> 1.8 X86InstrInfo.def updated: 1.36 -> 1.37 --- Log message: Make mem size an assert Add mem size flags to all instructions using an imm --- Diffs of the changes: Index: llvm/lib/Target/X86/MachineCodeEmitter.cpp diff -u llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.7 llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.8 --- llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.7 Thu Dec 12 20:13:15 2002 +++ llvm/lib/Target/X86/MachineCodeEmitter.cpp Thu Dec 12 21:50:13 2002 @@ -211,12 +211,7 @@ case X86II::MemArg64: return 8; case X86II::MemArg80: return 10; case X86II::MemArg128: return 16; - default: { - // FIXME: This should be an assert, but it is returning 4 because that was - // the former behavior and it's what was expected. Once the assumptions - // below are fixed, this can become an assert. - return 4; - } + default: assert(0 && "Memory size not set!"); } } Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.36 llvm/lib/Target/X86/X86InstrInfo.def:1.37 --- llvm/lib/Target/X86/X86InstrInfo.def:1.36 Thu Dec 12 17:19:11 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Thu Dec 12 21:50:13 2002 @@ -74,9 +74,9 @@ I(MOVrr8 , "movb", 0x88, 0, X86II::MRMDestReg, NoIR, NoIR) // R8 = R8 I(MOVrr16 , "movw", 0x89, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 = R16 I(MOVrr32 , "movl", 0x89, 0, X86II::MRMDestReg, NoIR, NoIR) // R32 = R32 -I(MOVir8 , "movb", 0xB0, 0, X86II::AddRegFrm, NoIR, NoIR) // R8 = imm8 -I(MOVir16 , "movw", 0xB8, 0, X86II::AddRegFrm | X86II::OpSize, NoIR, NoIR) // R16 = imm16 -I(MOVir32 , "movl", 0xB8, 0, X86II::AddRegFrm, NoIR, NoIR) // R32 = imm32 +I(MOVir8 , "movb", 0xB0, 0, X86II::AddRegFrm | X86II::MemArg8, NoIR, NoIR) // R8 = imm8 +I(MOVir16 , "movw", 0xB8, 0, X86II::AddRegFrm | X86II::MemArg16 | X86II::OpSize, NoIR, NoIR) // R16 = imm16 +I(MOVir32 , "movl", 0xB8, 0, X86II::AddRegFrm | X86II::MemArg32, NoIR, NoIR) // R32 = imm32 I(MOVmr8 , "movb", 0x8A, 0, X86II::MRMSrcMem | X86II::MemArg8, NoIR, NoIR) // R8 = [mem] I(MOVmr16 , "movw", 0x8B, 0, X86II::MRMSrcMem | X86II::OpSize | X86II::MemArg16, NoIR, NoIR) // R16 = [mem] @@ -96,11 +96,11 @@ I(ADDrr8 , "addb", 0x00, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 += R8 I(ADDrr16 , "addw", 0x01, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 += R16 I(ADDrr32 , "addl", 0x01, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 += R32 -I(ADDri32 , "add", 0x81, M_2_ADDR_FLAG, X86II::MRMS0r, NoIR, NoIR) // R32 += imm32 +I(ADDri32 , "add", 0x81, M_2_ADDR_FLAG, X86II::MRMS0r | X86II::MemArg32, NoIR, NoIR) // R32 += imm32 I(SUBrr8 , "subb", 0x2A, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 -= R8 I(SUBrr16 , "subw", 0x2B, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 -= R16 I(SUBrr32 , "subl", 0x2B, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 -= R32 -I(SUBri32 , "sub", 0x81, M_2_ADDR_FLAG, X86II::MRMS5r, NoIR, NoIR) // R32 -= imm32 +I(SUBri32 , "sub", 0x81, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::MemArg32, NoIR, NoIR) // R32 -= imm32 I(MULrr8 , "mulb", 0xF6, 0, X86II::MRMS4r | X86II::Void, O_AL, O_AX) // AX = AL*R8 I(MULrr16 , "mulw", 0xF7, 0, X86II::MRMS4r | X86II::Void | // DX:AX= AX*R16 X86II::OpSize, O_AX, T_AXDX) @@ -135,21 +135,21 @@ I(SHLrr8 , "shlb", 0xD2, M_2_ADDR_FLAG, X86II::MRMS4r, O_CL, NoIR) // R8 <<= cl I(SHLrr16 , "shlw", 0xD3, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::OpSize, O_CL, NoIR) // R16 <<= cl I(SHLrr32 , "shll", 0xD3, M_2_ADDR_FLAG, X86II::MRMS4r, O_CL, NoIR) // R32 <<= cl -I(SHLir8 , "shlb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS4r, NoIR, NoIR) // R8 <<= imm8 -I(SHLir16 , "shlw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::OpSize, NoIR, NoIR) // R16 <<= imm8 -I(SHLir32 , "shll", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r, NoIR, NoIR) // R32 <<= imm8 +I(SHLir8 , "shlb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::MemArg8, NoIR, NoIR) // R8 <<= imm8 +I(SHLir16 , "shlw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::MemArg8 | X86II::OpSize, NoIR, NoIR) // R16 <<= imm8 +I(SHLir32 , "shll", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::MemArg8, NoIR, NoIR) // R32 <<= imm8 I(SHRrr8 , "shrb", 0xD2, M_2_ADDR_FLAG, X86II::MRMS5r, O_CL, NoIR) // R8 >>>= cl I(SHRrr16 , "shrw", 0xD3, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::OpSize, O_CL, NoIR) // R16 >>>= cl I(SHRrr32 , "shrl", 0xD3, M_2_ADDR_FLAG, X86II::MRMS5r, O_CL, NoIR) // R32 >>>= cl -I(SHRir8 , "shrb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS5r, NoIR, NoIR) // R8 >>>= imm8 -I(SHRir16 , "shrw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::OpSize, NoIR, NoIR) // R16 >>>= imm8 -I(SHRir32 , "shrl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r, NoIR, NoIR) // R32 >>>= imm8 +I(SHRir8 , "shrb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::MemArg8, NoIR, NoIR) // R8 >>>= imm8 +I(SHRir16 , "shrw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::MemArg8 | X86II::OpSize, NoIR, NoIR) // R16 >>>= imm8 +I(SHRir32 , "shrl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::MemArg8, NoIR, NoIR) // R32 >>>= imm8 I(SARrr8 , "sarb", 0xD2, M_2_ADDR_FLAG, X86II::MRMS7r, O_CL, NoIR) // R8 >>= cl I(SARrr16 , "sarw", 0xD3, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::OpSize, O_CL, NoIR) // R16 >>= cl I(SARrr32 , "sarl", 0xD3, M_2_ADDR_FLAG, X86II::MRMS7r, O_CL, NoIR) // R32 >>= cl -I(SARir8 , "sarb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS7r, NoIR, NoIR) // R8 >>= imm8 -I(SARir16 , "sarw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::OpSize, NoIR, NoIR) // R16 >>= imm8 -I(SARir32 , "sarl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r, NoIR, NoIR) // R32 >>= imm8 +I(SARir8 , "sarb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::MemArg8, NoIR, NoIR) // R8 >>= imm8 +I(SARir16 , "sarw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::MemArg8 | X86II::OpSize, NoIR, NoIR) // R16 >>= imm8 +I(SARir32 , "sarl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::MemArg8, NoIR, NoIR) // R32 >>= imm8 // Floating point loads I(FLDr32 , "flds", 0xD9, 0, X86II::MRMS0m, NoIR, NoIR) // push float @@ -178,7 +178,7 @@ I(CMPrr8 , "cmpb", 0x38, 0, X86II::MRMDestReg, NoIR, NoIR) // compare R8,R8 I(CMPrr16 , "cmpw", 0x39, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // compare R16,R16 I(CMPrr32 , "cmpl", 0x39, 0, X86II::MRMDestReg, NoIR, NoIR) // compare R32,R32 -I(CMPri8 , "cmp", 0x80, 0, X86II::MRMS7r, NoIR, NoIR) // compare R8, imm8 +I(CMPri8 , "cmp", 0x80, 0, X86II::MRMS7r | X86II::MemArg8, NoIR, NoIR) // compare R8, imm8 // Sign extenders (first 3 are good for DIV/IDIV; the others are more general) I(CBW , "cbw", 0x98, 0, X86II::RawFrm, O_AL, O_AX) // AX = signext(AL) From lattner at cs.uiuc.edu Thu Dec 12 21:53:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 21:53:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/MachineCodeEmitter.cpp Printer.cpp X86InstrInfo.def X86InstrInfo.h Message-ID: <200212130352.VAA26840@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: MachineCodeEmitter.cpp updated: 1.8 -> 1.9 Printer.cpp updated: 1.24 -> 1.25 X86InstrInfo.def updated: 1.37 -> 1.38 X86InstrInfo.h updated: 1.16 -> 1.17 --- Log message: Rename MemArg* to Arg* --- Diffs of the changes: Index: llvm/lib/Target/X86/MachineCodeEmitter.cpp diff -u llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.8 llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.9 --- llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.8 Thu Dec 12 21:50:13 2002 +++ llvm/lib/Target/X86/MachineCodeEmitter.cpp Thu Dec 12 21:51:55 2002 @@ -204,13 +204,13 @@ } unsigned sizeOfPtr (const MachineInstrDescriptor &Desc) { - switch (Desc.TSFlags & X86II::MemArgMask) { - case X86II::MemArg8: return 1; - case X86II::MemArg16: return 2; - case X86II::MemArg32: return 4; - case X86II::MemArg64: return 8; - case X86II::MemArg80: return 10; - case X86II::MemArg128: return 16; + switch (Desc.TSFlags & X86II::ArgMask) { + case X86II::Arg8: return 1; + case X86II::Arg16: return 2; + case X86II::Arg32: return 4; + case X86II::Arg64: return 8; + case X86II::Arg80: return 10; + case X86II::Arg128: return 16; default: assert(0 && "Memory size not set!"); } } Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.24 llvm/lib/Target/X86/Printer.cpp:1.25 --- llvm/lib/Target/X86/Printer.cpp:1.24 Thu Dec 5 02:30:40 2002 +++ llvm/lib/Target/X86/Printer.cpp Thu Dec 12 21:51:55 2002 @@ -120,13 +120,13 @@ } static const std::string sizePtr (const MachineInstrDescriptor &Desc) { - switch (Desc.TSFlags & X86II::MemArgMask) { - case X86II::MemArg8: return "BYTE PTR"; - case X86II::MemArg16: return "WORD PTR"; - case X86II::MemArg32: return "DWORD PTR"; - case X86II::MemArg64: return "QWORD PTR"; - case X86II::MemArg80: return "XWORD PTR"; - case X86II::MemArg128: return "128BIT PTR"; // dunno what the real one is + switch (Desc.TSFlags & X86II::ArgMask) { + case X86II::Arg8: return "BYTE PTR"; + case X86II::Arg16: return "WORD PTR"; + case X86II::Arg32: return "DWORD PTR"; + case X86II::Arg64: return "QWORD PTR"; + case X86II::Arg80: return "XWORD PTR"; + case X86II::Arg128: return "128BIT PTR"; // dunno what the real one is default: return " PTR"; // crack being smoked } } Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.37 llvm/lib/Target/X86/X86InstrInfo.def:1.38 --- llvm/lib/Target/X86/X86InstrInfo.def:1.37 Thu Dec 12 21:50:13 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Thu Dec 12 21:51:55 2002 @@ -74,20 +74,20 @@ I(MOVrr8 , "movb", 0x88, 0, X86II::MRMDestReg, NoIR, NoIR) // R8 = R8 I(MOVrr16 , "movw", 0x89, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 = R16 I(MOVrr32 , "movl", 0x89, 0, X86II::MRMDestReg, NoIR, NoIR) // R32 = R32 -I(MOVir8 , "movb", 0xB0, 0, X86II::AddRegFrm | X86II::MemArg8, NoIR, NoIR) // R8 = imm8 -I(MOVir16 , "movw", 0xB8, 0, X86II::AddRegFrm | X86II::MemArg16 | X86II::OpSize, NoIR, NoIR) // R16 = imm16 -I(MOVir32 , "movl", 0xB8, 0, X86II::AddRegFrm | X86II::MemArg32, NoIR, NoIR) // R32 = imm32 -I(MOVmr8 , "movb", 0x8A, 0, X86II::MRMSrcMem | X86II::MemArg8, NoIR, NoIR) // R8 = [mem] +I(MOVir8 , "movb", 0xB0, 0, X86II::AddRegFrm | X86II::Arg8, NoIR, NoIR) // R8 = imm8 +I(MOVir16 , "movw", 0xB8, 0, X86II::AddRegFrm | X86II::Arg16 | X86II::OpSize, NoIR, NoIR) // R16 = imm16 +I(MOVir32 , "movl", 0xB8, 0, X86II::AddRegFrm | X86II::Arg32, NoIR, NoIR) // R32 = imm32 +I(MOVmr8 , "movb", 0x8A, 0, X86II::MRMSrcMem | X86II::Arg8, NoIR, NoIR) // R8 = [mem] I(MOVmr16 , "movw", 0x8B, 0, X86II::MRMSrcMem | X86II::OpSize | - X86II::MemArg16, NoIR, NoIR) // R16 = [mem] -I(MOVmr32 , "movl", 0x8B, 0, X86II::MRMSrcMem | X86II::MemArg32, NoIR, + X86II::Arg16, NoIR, NoIR) // R16 = [mem] +I(MOVmr32 , "movl", 0x8B, 0, X86II::MRMSrcMem | X86II::Arg32, NoIR, NoIR) // R32 = [mem] I(MOVrm8 , "movb", 0x88, 0, X86II::MRMDestMem | X86II::Void | - X86II::MemArg8, NoIR, NoIR) // [mem] = R8 + X86II::Arg8, NoIR, NoIR) // [mem] = R8 I(MOVrm16 , "movw", 0x89, 0, X86II::MRMDestMem | X86II::Void | - X86II::OpSize | X86II::MemArg16, NoIR, NoIR) // [mem] = R16 + X86II::OpSize | X86II::Arg16, NoIR, NoIR) // [mem] = R16 I(MOVrm32 , "movl", 0x89, 0, X86II::MRMDestMem | X86II::Void | - X86II::MemArg32, NoIR, NoIR) // [mem] = R32 + X86II::Arg32, NoIR, NoIR) // [mem] = R32 I(PUSHr32 , "pushl", 0x50, 0, X86II::AddRegFrm | X86II::Void, NoIR, NoIR) I(POPr32 , "popl", 0x58, 0, X86II::AddRegFrm, NoIR, NoIR) @@ -96,11 +96,11 @@ I(ADDrr8 , "addb", 0x00, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 += R8 I(ADDrr16 , "addw", 0x01, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 += R16 I(ADDrr32 , "addl", 0x01, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 += R32 -I(ADDri32 , "add", 0x81, M_2_ADDR_FLAG, X86II::MRMS0r | X86II::MemArg32, NoIR, NoIR) // R32 += imm32 +I(ADDri32 , "add", 0x81, M_2_ADDR_FLAG, X86II::MRMS0r | X86II::Arg32, NoIR, NoIR) // R32 += imm32 I(SUBrr8 , "subb", 0x2A, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 -= R8 I(SUBrr16 , "subw", 0x2B, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 -= R16 I(SUBrr32 , "subl", 0x2B, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 -= R32 -I(SUBri32 , "sub", 0x81, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::MemArg32, NoIR, NoIR) // R32 -= imm32 +I(SUBri32 , "sub", 0x81, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::Arg32, NoIR, NoIR) // R32 -= imm32 I(MULrr8 , "mulb", 0xF6, 0, X86II::MRMS4r | X86II::Void, O_AL, O_AX) // AX = AL*R8 I(MULrr16 , "mulw", 0xF7, 0, X86II::MRMS4r | X86II::Void | // DX:AX= AX*R16 X86II::OpSize, O_AX, T_AXDX) @@ -135,21 +135,21 @@ I(SHLrr8 , "shlb", 0xD2, M_2_ADDR_FLAG, X86II::MRMS4r, O_CL, NoIR) // R8 <<= cl I(SHLrr16 , "shlw", 0xD3, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::OpSize, O_CL, NoIR) // R16 <<= cl I(SHLrr32 , "shll", 0xD3, M_2_ADDR_FLAG, X86II::MRMS4r, O_CL, NoIR) // R32 <<= cl -I(SHLir8 , "shlb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::MemArg8, NoIR, NoIR) // R8 <<= imm8 -I(SHLir16 , "shlw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::MemArg8 | X86II::OpSize, NoIR, NoIR) // R16 <<= imm8 -I(SHLir32 , "shll", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::MemArg8, NoIR, NoIR) // R32 <<= imm8 +I(SHLir8 , "shlb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::Arg8, NoIR, NoIR) // R8 <<= imm8 +I(SHLir16 , "shlw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::Arg8 | X86II::OpSize, NoIR, NoIR) // R16 <<= imm8 +I(SHLir32 , "shll", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::Arg8, NoIR, NoIR) // R32 <<= imm8 I(SHRrr8 , "shrb", 0xD2, M_2_ADDR_FLAG, X86II::MRMS5r, O_CL, NoIR) // R8 >>>= cl I(SHRrr16 , "shrw", 0xD3, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::OpSize, O_CL, NoIR) // R16 >>>= cl I(SHRrr32 , "shrl", 0xD3, M_2_ADDR_FLAG, X86II::MRMS5r, O_CL, NoIR) // R32 >>>= cl -I(SHRir8 , "shrb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::MemArg8, NoIR, NoIR) // R8 >>>= imm8 -I(SHRir16 , "shrw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::MemArg8 | X86II::OpSize, NoIR, NoIR) // R16 >>>= imm8 -I(SHRir32 , "shrl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::MemArg8, NoIR, NoIR) // R32 >>>= imm8 +I(SHRir8 , "shrb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::Arg8, NoIR, NoIR) // R8 >>>= imm8 +I(SHRir16 , "shrw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::Arg8 | X86II::OpSize, NoIR, NoIR) // R16 >>>= imm8 +I(SHRir32 , "shrl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::Arg8, NoIR, NoIR) // R32 >>>= imm8 I(SARrr8 , "sarb", 0xD2, M_2_ADDR_FLAG, X86II::MRMS7r, O_CL, NoIR) // R8 >>= cl I(SARrr16 , "sarw", 0xD3, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::OpSize, O_CL, NoIR) // R16 >>= cl I(SARrr32 , "sarl", 0xD3, M_2_ADDR_FLAG, X86II::MRMS7r, O_CL, NoIR) // R32 >>= cl -I(SARir8 , "sarb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::MemArg8, NoIR, NoIR) // R8 >>= imm8 -I(SARir16 , "sarw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::MemArg8 | X86II::OpSize, NoIR, NoIR) // R16 >>= imm8 -I(SARir32 , "sarl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::MemArg8, NoIR, NoIR) // R32 >>= imm8 +I(SARir8 , "sarb", 0xC0, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::Arg8, NoIR, NoIR) // R8 >>= imm8 +I(SARir16 , "sarw", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::Arg8 | X86II::OpSize, NoIR, NoIR) // R16 >>= imm8 +I(SARir32 , "sarl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::Arg8, NoIR, NoIR) // R32 >>= imm8 // Floating point loads I(FLDr32 , "flds", 0xD9, 0, X86II::MRMS0m, NoIR, NoIR) // push float @@ -178,7 +178,7 @@ I(CMPrr8 , "cmpb", 0x38, 0, X86II::MRMDestReg, NoIR, NoIR) // compare R8,R8 I(CMPrr16 , "cmpw", 0x39, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // compare R16,R16 I(CMPrr32 , "cmpl", 0x39, 0, X86II::MRMDestReg, NoIR, NoIR) // compare R32,R32 -I(CMPri8 , "cmp", 0x80, 0, X86II::MRMS7r | X86II::MemArg8, NoIR, NoIR) // compare R8, imm8 +I(CMPri8 , "cmp", 0x80, 0, X86II::MRMS7r | X86II::Arg8, NoIR, NoIR) // compare R8, imm8 // Sign extenders (first 3 are good for DIV/IDIV; the others are more general) I(CBW , "cbw", 0x98, 0, X86II::RawFrm, O_AL, O_AX) // AX = signext(AL) Index: llvm/lib/Target/X86/X86InstrInfo.h diff -u llvm/lib/Target/X86/X86InstrInfo.h:1.16 llvm/lib/Target/X86/X86InstrInfo.h:1.17 --- llvm/lib/Target/X86/X86InstrInfo.h:1.16 Thu Dec 5 02:30:40 2002 +++ llvm/lib/Target/X86/X86InstrInfo.h Thu Dec 12 21:51:55 2002 @@ -84,13 +84,13 @@ // This three-bit field describes the size of a memory operand. // I'm just being paranoid not using the zero value; there's // probably no reason you couldn't use it. - MemArg8 = 0x1 << 8, - MemArg16 = 0x2 << 8, - MemArg32 = 0x3 << 8, - MemArg64 = 0x4 << 8, - MemArg80 = 0x5 << 8, - MemArg128 = 0x6 << 8, - MemArgMask = 0x7 << 8, + Arg8 = 0x1 << 8, + Arg16 = 0x2 << 8, + Arg32 = 0x3 << 8, + Arg64 = 0x4 << 8, + Arg80 = 0x5 << 8, + Arg128 = 0x6 << 8, + ArgMask = 0x7 << 8, }; } From lattner at cs.uiuc.edu Thu Dec 12 22:13:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 22:13:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212130412.WAA27404@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.54 -> 1.55 --- Log message: Remove extranous #include --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.54 llvm/lib/Target/X86/InstSelectSimple.cpp:1.55 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.54 Thu Dec 12 09:33:39 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Thu Dec 12 22:12:24 2002 @@ -23,7 +23,6 @@ #include "llvm/Support/InstVisitor.h" #include "llvm/Target/MRegisterInfo.h" #include -#include using namespace MOTy; // Get Use, Def, UseAndDef From brukman at cs.uiuc.edu Thu Dec 12 22:26:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Dec 12 22:26:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp Message-ID: <200212130425.WAA28234@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.9 -> 1.10 --- Log message: Moves now select correct opcode based on the data size. --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.9 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.10 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.9 Wed Dec 4 17:57:03 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Thu Dec 12 22:24:53 2002 @@ -23,7 +23,6 @@ : MRegisterInfo(X86Regs, sizeof(X86Regs)/sizeof(X86Regs[0])) { } - MachineBasicBlock::iterator X86RegisterInfo::storeReg2RegOffset(MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI, @@ -31,7 +30,15 @@ unsigned ImmOffset, unsigned dataSize) const { - MachineInstr *MI = addRegOffset(BuildMI(X86::MOVrm32, 5), + unsigned opcode; + switch (dataSize) { + case 1: opcode = X86::MOVrm8; break; + case 2: opcode = X86::MOVrm16; break; + case 4: opcode = X86::MOVrm32; break; + default: assert(0 && "Invalid data size!"); + } + + MachineInstr *MI = addRegOffset(BuildMI(opcode, 5), DestReg, ImmOffset).addReg(SrcReg); return ++(MBB->insert(MBBI, MI)); } @@ -43,7 +50,15 @@ unsigned ImmOffset, unsigned dataSize) const { - MachineInstr *MI = addRegOffset(BuildMI(X86::MOVmr32, 5).addReg(DestReg), + unsigned opcode; + switch (dataSize) { + case 1: opcode = X86::MOVmr8; break; + case 2: opcode = X86::MOVmr16; break; + case 4: opcode = X86::MOVmr32; break; + default: assert(0 && "Invalid data size!"); + } + + MachineInstr *MI = addRegOffset(BuildMI(opcode, 5).addReg(DestReg), SrcReg, ImmOffset); return ++(MBB->insert(MBBI, MI)); } From brukman at cs.uiuc.edu Thu Dec 12 22:35:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Dec 12 22:35:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212130434.WAA29173@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.6 -> 1.7 --- Log message: Start allocating stack space at [ebp-4] to not overwrite the return address. Also make all loads & stores 4-byte aligned for performance. ;) --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.6 llvm/lib/CodeGen/RegAllocSimple.cpp:1.7 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.6 Thu Dec 12 17:20:31 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Thu Dec 12 22:34:02 2002 @@ -50,13 +50,15 @@ RegAllocSimple(TargetMachine &tm) : TM(tm), CurrMBB(0), maxOffset(0), RegInfo(tm.getRegisterInfo()), - NumBytesAllocated(0), ByteAlignment(4) + ByteAlignment(4) { // build reverse mapping for physReg -> register class RegInfo->buildReg2RegClassMap(PhysReg2RegClassMap); RegsUsed[RegInfo->getFramePointer()] = 1; RegsUsed[RegInfo->getStackPointer()] = 1; + + cleanupAfterFunction(); } bool isAvailableReg(unsigned Reg) { @@ -80,7 +82,7 @@ void cleanupAfterFunction() { RegMap.clear(); SSA2PhysRegMap.clear(); - NumBytesAllocated = 0; + NumBytesAllocated = 4; } /// Moves value from memory into that register @@ -112,6 +114,7 @@ const TargetRegisterClass *regClass) { if (RegMap.find(VirtReg) == RegMap.end()) { +#if 0 unsigned size = regClass->getDataSize(); unsigned over = NumBytesAllocated - (NumBytesAllocated % ByteAlignment); if (size >= ByteAlignment - over) { @@ -120,6 +123,10 @@ } RegMap[VirtReg] = NumBytesAllocated; NumBytesAllocated += size; +#endif + // FIXME: forcing each arg to take 4 bytes on the stack + RegMap[VirtReg] = NumBytesAllocated; + NumBytesAllocated += 4; } return RegMap[VirtReg]; } From lattner at cs.uiuc.edu Thu Dec 12 22:42:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 22:42:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.def Message-ID: <200212130441.WAA29606@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.def updated: 1.38 -> 1.39 --- Log message: Fix encoding of CBW instruction --- Diffs of the changes: Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.38 llvm/lib/Target/X86/X86InstrInfo.def:1.39 --- llvm/lib/Target/X86/X86InstrInfo.def:1.38 Thu Dec 12 21:51:55 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Thu Dec 12 22:41:31 2002 @@ -181,7 +181,7 @@ I(CMPri8 , "cmp", 0x80, 0, X86II::MRMS7r | X86II::Arg8, NoIR, NoIR) // compare R8, imm8 // Sign extenders (first 3 are good for DIV/IDIV; the others are more general) -I(CBW , "cbw", 0x98, 0, X86II::RawFrm, O_AL, O_AX) // AX = signext(AL) +I(CBW , "cbw", 0x98, 0, X86II::RawFrm | X86II::OpSize, O_AL, O_AX) // AX = signext(AL) I(CWD , "cwd", 0x99, 0, X86II::RawFrm, O_AX, O_DX) // DX:AX = signext(AX) I(CDQ , "cdq", 0x99, 0, X86II::RawFrm, O_EAX, O_EDX) // EDX:EAX = signext(EAX) I(MOVSXr16r8 , "movsx", 0xBE, 0, X86II::MRMSrcReg | X86II::TB | // R16 = signext(R8) From brukman at cs.uiuc.edu Thu Dec 12 22:44:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Dec 12 22:44:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-call.ll Message-ID: <200212130443.WAA29681@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-call.ll updated: 1.2 -> 1.3 --- Log message: This way it's easier to test: if the call to external exit(0) succeeded, program exits with code 0, no error. If the call does not work/succeed, main returns 1, so we notice it. The other way around doesn't work. :) --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-call.ll diff -u llvm/test/Regression/Jello/test-call.ll:1.2 llvm/test/Regression/Jello/test-call.ll:1.3 --- llvm/test/Regression/Jello/test-call.ll:1.2 Wed Dec 4 11:15:07 2002 +++ llvm/test/Regression/Jello/test-call.ll Thu Dec 12 22:43:32 2002 @@ -1,7 +1,7 @@ declare void %exit(int) -void %main() { - call void %exit(int 1) - ret void +int %main() { + call void %exit(int 0) + ret int 1 } From lattner at cs.uiuc.edu Thu Dec 12 23:05:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 23:05:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.def Message-ID: <200212130504.XAA30651@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.def updated: 1.39 -> 1.40 --- Log message: Nicify a bit --- Diffs of the changes: Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.39 llvm/lib/Target/X86/X86InstrInfo.def:1.40 --- llvm/lib/Target/X86/X86InstrInfo.def:1.39 Thu Dec 12 22:41:31 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Thu Dec 12 23:04:37 2002 @@ -80,8 +80,7 @@ I(MOVmr8 , "movb", 0x8A, 0, X86II::MRMSrcMem | X86II::Arg8, NoIR, NoIR) // R8 = [mem] I(MOVmr16 , "movw", 0x8B, 0, X86II::MRMSrcMem | X86II::OpSize | X86II::Arg16, NoIR, NoIR) // R16 = [mem] -I(MOVmr32 , "movl", 0x8B, 0, X86II::MRMSrcMem | X86II::Arg32, NoIR, - NoIR) // R32 = [mem] +I(MOVmr32 , "movl", 0x8B, 0, X86II::MRMSrcMem | X86II::Arg32, NoIR, NoIR)// R32 = [mem] I(MOVrm8 , "movb", 0x88, 0, X86II::MRMDestMem | X86II::Void | X86II::Arg8, NoIR, NoIR) // [mem] = R8 I(MOVrm16 , "movw", 0x89, 0, X86II::MRMDestMem | X86II::Void | From lattner at cs.uiuc.edu Thu Dec 12 23:06:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 23:06:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/MachineCodeEmitter.cpp Message-ID: <200212130505.XAA30663@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: MachineCodeEmitter.cpp updated: 1.9 -> 1.10 --- Log message: Emit the right form of mod/rm mod field --- Diffs of the changes: Index: llvm/lib/Target/X86/MachineCodeEmitter.cpp diff -u llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.9 llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.10 --- llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.9 Thu Dec 12 21:51:55 2002 +++ llvm/lib/Target/X86/MachineCodeEmitter.cpp Thu Dec 12 23:05:05 2002 @@ -148,7 +148,7 @@ emitConstant(Disp.getImmedValue(), 1); } else { // Emit the most general non-SIB encoding: [REG+disp32] - MCE.emitByte(ModRMByte(1, RegOpcodeField, BaseRegNo)); + MCE.emitByte(ModRMByte(2, RegOpcodeField, BaseRegNo)); emitConstant(Disp.getImmedValue(), 4); } } From lattner at cs.uiuc.edu Thu Dec 12 23:30:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 23:30:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-branch.ll Message-ID: <200212130529.XAA30793@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-branch.ll updated: 1.3 -> 1.4 --- Log message: Infinite loops, are, well, not good --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-branch.ll diff -u llvm/test/Regression/Jello/test-branch.ll:1.3 llvm/test/Regression/Jello/test-branch.ll:1.4 --- llvm/test/Regression/Jello/test-branch.ll:1.3 Wed Dec 4 11:15:07 2002 +++ llvm/test/Regression/Jello/test-branch.ll Thu Dec 12 23:28:50 2002 @@ -2,7 +2,7 @@ void %main() { br label %Test Test: - %X = setne int 0, 4 + %X = seteq int 0, 4 br bool %X, label %Test, label %Label Label: ret void From lattner at cs.uiuc.edu Thu Dec 12 23:41:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 23:41:01 2002 Subject: [llvm-commits] CVS: llvm/tools/jello/Emitter.cpp VM.cpp Message-ID: <200212130540.XAA31512@apoc.cs.uiuc.edu> Changes in directory llvm/tools/jello: Emitter.cpp updated: 1.3 -> 1.4 VM.cpp updated: 1.4 -> 1.5 --- Log message: Implement branches --- Diffs of the changes: Index: llvm/tools/jello/Emitter.cpp diff -u llvm/tools/jello/Emitter.cpp:1.3 llvm/tools/jello/Emitter.cpp:1.4 --- llvm/tools/jello/Emitter.cpp:1.3 Wed Dec 4 00:45:40 2002 +++ llvm/tools/jello/Emitter.cpp Thu Dec 12 23:40:28 2002 @@ -8,6 +8,7 @@ #include "VM.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Function.h" namespace { class Emitter : public MachineCodeEmitter { @@ -15,12 +16,15 @@ unsigned char *CurBlock; unsigned char *CurByte; + + std::vector > BBRefs; + std::map BBLocations; public: Emitter(VM &vm) : TheVM(vm) {} virtual void startFunction(MachineFunction &F); virtual void finishFunction(MachineFunction &F); - virtual void startBasicBlock(MachineBasicBlock &BB) {} + virtual void startBasicBlock(MachineBasicBlock &BB); virtual void emitByte(unsigned char B); virtual void emitPCRelativeDisp(Value *V); virtual void emitGlobalAddress(GlobalValue *V); @@ -48,15 +52,23 @@ TheVM.addGlobalMapping(F.getFunction(), CurBlock); } -#include -#include "llvm/Function.h" - void Emitter::finishFunction(MachineFunction &F) { + for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { + unsigned Location = BBLocations[BBRefs[i].first]; + unsigned *Ref = BBRefs[i].second; + *Ref = Location-(unsigned)Ref-4; + } + BBRefs.clear(); + BBLocations.clear(); + std::cerr << "Finished Code Generation of Function: " << F.getFunction()->getName() << ": " << CurByte-CurBlock << " bytes of text\n"; } +void Emitter::startBasicBlock(MachineBasicBlock &BB) { + BBLocations[BB.getBasicBlock()] = (unsigned)CurByte; +} void Emitter::emitByte(unsigned char B) { @@ -64,16 +76,24 @@ } -// emitPCRelativeDisp - Just output a displacement that will cause a reference -// to the zero page, which will cause a seg-fault, causing things to get -// resolved on demand. Keep track of these markers. +// emitPCRelativeDisp - For functions, just output a displacement that will +// cause a reference to the zero page, which will cause a seg-fault, causing +// things to get resolved on demand. Keep track of these markers. +// +// For basic block references, keep track of where the references are so they +// may be patched up when the basic block is defined. // void Emitter::emitPCRelativeDisp(Value *V) { - TheVM.addFunctionRef(CurByte, cast(V)); - - unsigned ZeroAddr = -(unsigned)CurByte-4; // Calculate displacement to null - *(unsigned*)CurByte = ZeroAddr; // 4 byte offset - CurByte += 4; + if (Function *F = dyn_cast(V)) { + TheVM.addFunctionRef(CurByte, F); + unsigned ZeroAddr = -(unsigned)CurByte-4; // Calculate displacement to null + *(unsigned*)CurByte = ZeroAddr; // 4 byte offset + CurByte += 4; + } else { + BasicBlock *BB = cast(V); // Keep track of reference... + BBRefs.push_back(std::make_pair(BB, (unsigned*)CurByte)); + CurByte += 4; + } } void Emitter::emitGlobalAddress(GlobalValue *V) { Index: llvm/tools/jello/VM.cpp diff -u llvm/tools/jello/VM.cpp:1.4 llvm/tools/jello/VM.cpp:1.5 --- llvm/tools/jello/VM.cpp:1.4 Wed Dec 4 00:45:40 2002 +++ llvm/tools/jello/VM.cpp Thu Dec 12 23:40:28 2002 @@ -9,7 +9,6 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/Function.h" -#include #include // dlsym access From lattner at cs.uiuc.edu Thu Dec 12 23:44:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 23:44:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-ret.ll Message-ID: <200212130543.XAA32123@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-ret.ll updated: 1.2 -> 1.3 --- Log message: Fix testcase --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-ret.ll diff -u llvm/test/Regression/Jello/test-ret.ll:1.2 llvm/test/Regression/Jello/test-ret.ll:1.3 --- llvm/test/Regression/Jello/test-ret.ll:1.2 Wed Dec 4 11:15:07 2002 +++ llvm/test/Regression/Jello/test-ret.ll Thu Dec 12 23:42:57 2002 @@ -5,7 +5,7 @@ ubyte %test() { ret ubyte 1 } short %test() { ret short -1 } ushort %test() { ret ushort 65535 } -int %main() { ret int -1 } +int %main() { ret int 0 } uint %test() { ret uint 4 } ;long %test() { ret void } ;ulong %test() { ret void } From brukman at cs.uiuc.edu Thu Dec 12 23:44:03 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Dec 12 23:44:03 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-setcond-int.ll Message-ID: <200212130543.XAA32187@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-setcond-int.ll updated: 1.2 -> 1.3 --- Log message: Making main() return 0 to exit without error when no error actually occurs. --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-setcond-int.ll diff -u llvm/test/Regression/Jello/test-setcond-int.ll:1.2 llvm/test/Regression/Jello/test-setcond-int.ll:1.3 --- llvm/test/Regression/Jello/test-setcond-int.ll:1.2 Thu Nov 7 12:09:02 2002 +++ llvm/test/Regression/Jello/test-setcond-int.ll Thu Dec 12 23:43:36 2002 @@ -1,5 +1,5 @@ -void %main() { +int %main() { %int1 = add int 0, 0 %int2 = add int 0, 0 ;%long1 = add long 0, 0 @@ -64,5 +64,5 @@ ;%test46 = setle long %long1, %long2 ;%test47 = setlt long %long1, %long2 ;%test48 = setne long %long1, %long2 - ret void + ret int 0 } From brukman at cs.uiuc.edu Thu Dec 12 23:45:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Dec 12 23:45:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-arith.ll test-shift.ll Message-ID: <200212130544.XAA32279@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-arith.ll updated: 1.4 -> 1.5 test-shift.ll updated: 1.1 -> 1.2 --- Log message: Making main() return 0 so that we know it ran successfully when it exits. --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-arith.ll diff -u llvm/test/Regression/Jello/test-arith.ll:1.4 llvm/test/Regression/Jello/test-arith.ll:1.5 --- llvm/test/Regression/Jello/test-arith.ll:1.4 Wed Dec 4 11:15:07 2002 +++ llvm/test/Regression/Jello/test-arith.ll Thu Dec 12 23:44:21 2002 @@ -1,5 +1,5 @@ -void %main() { +int %main() { %A = add sbyte 0, 12 %B = sub sbyte %A, %A %C = mul sbyte %B, %B @@ -24,5 +24,5 @@ %F = div uint 5, 6 %G = rem uint 6, 5 - ret void + ret int 0 } Index: llvm/test/Regression/Jello/test-shift.ll diff -u llvm/test/Regression/Jello/test-shift.ll:1.1 llvm/test/Regression/Jello/test-shift.ll:1.2 --- llvm/test/Regression/Jello/test-shift.ll:1.1 Thu Oct 31 17:05:22 2002 +++ llvm/test/Regression/Jello/test-shift.ll Thu Dec 12 23:44:21 2002 @@ -1,5 +1,5 @@ ; test shifts -void %main() { +int %main() { %i = add int 10, 0 %u = add uint 20, 0 %shamt = add ubyte 0, 0 @@ -23,5 +23,5 @@ %temp07 = shr int %i, ubyte 6 ; 1 1 1 %temp08 = shr uint %u, ubyte 7 - ret void + ret int 0 } From lattner at cs.uiuc.edu Thu Dec 12 23:52:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 12 23:52:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-arith.ll Message-ID: <200212130551.XAA00465@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-arith.ll updated: 1.5 -> 1.6 --- Log message: Stop sucking --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-arith.ll diff -u llvm/test/Regression/Jello/test-arith.ll:1.5 llvm/test/Regression/Jello/test-arith.ll:1.6 --- llvm/test/Regression/Jello/test-arith.ll:1.5 Thu Dec 12 23:44:21 2002 +++ llvm/test/Regression/Jello/test-arith.ll Thu Dec 12 23:51:32 2002 @@ -1,7 +1,7 @@ int %main() { %A = add sbyte 0, 12 - %B = sub sbyte %A, %A + %B = sub sbyte %A, 1 %C = mul sbyte %B, %B %D = div sbyte %C, %C %E = rem sbyte %D, %D @@ -9,7 +9,7 @@ %G = rem ubyte 6, 5 %A = add short 0, 12 - %B = sub short %A, %A + %B = sub short %A, 1 %C = mul short %B, %B %D = div short %C, %C %E = rem short %D, %D @@ -17,7 +17,7 @@ %G = rem uint 6, 5 %A = add int 0, 12 - %B = sub int %A, %A + %B = sub int %A, 1 %C = mul int %B, %B %D = div int %C, %C %E = rem int %D, %D From lattner at cs.uiuc.edu Fri Dec 13 00:02:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 00:02:01 2002 Subject: [llvm-commits] CVS: llvm/www/docs/LangRef.html Message-ID: <200212130601.AAA26330@tank.cs.uiuc.edu> Changes in directory llvm/www/docs: LangRef.html updated: 1.19 -> 1.20 --- Log message: getelementptr uses long instead of uint indexes --- Diffs of the changes: Index: llvm/www/docs/LangRef.html diff -u llvm/www/docs/LangRef.html:1.19 llvm/www/docs/LangRef.html:1.20 --- llvm/www/docs/LangRef.html:1.19 Mon Nov 4 18:21:03 2002 +++ llvm/www/docs/LangRef.html Fri Dec 13 00:01:21 2002 @@ -490,7 +490,7 @@ ; Definition of main function int "main"() { ; int()* ; Convert [13x sbyte]* to sbyte *... - %cast210 = getelementptr [13 x sbyte]* %.LC0, uint 0, uint 0 ; sbyte* + %cast210 = getelementptr [13 x sbyte]* %.LC0, long 0, long 0 ; sbyte* ; Call puts function to write out the string to stdout... call int %puts(sbyte* %cast210) ; int @@ -1401,7 +1401,7 @@
Syntax:
-  <result> = getelementptr <ty>* <ptrval>{, uint <aidx>|, ubyte <sidx>}*
+  <result> = getelementptr <ty>* <ptrval>{, long <aidx>|, ubyte <sidx>}*
 
Overview:
@@ -1411,7 +1411,7 @@
Arguments:
-This instruction takes a list of uint values and ubyte +This instruction takes a list of long values and ubyte constants that indicate what form of addressing to perform. The actual types of the arguments provided depend on the type of the first pointer argument. The 'getelementptr' instruction is used to index down through the type @@ -1444,7 +1444,7 @@ %ST = type { int, double, %RT } int* "foo"(%ST* %s) { - %reg = getelementptr %ST* %s, uint 1, ubyte 2, ubyte 1, uint 5, uint 13 + %reg = getelementptr %ST* %s, long 1, ubyte 2, ubyte 1, long 5, long 13 ret int* %reg } @@ -1453,7 +1453,7 @@ The index types specified for the 'getelementptr' instruction depend on the pointer type that is being index into. Pointer and -array types require 'uint' values, and array types require 'long' values, and structure types require 'ubyte' constants.

@@ -1473,11 +1473,11 @@

 int* "foo"(%ST* %s) {
-  %t1 = getelementptr %ST* %s , uint 1                        ; yields %ST*:%t1
-  %t2 = getelementptr %ST* %t1, uint 0, ubyte 2               ; yields %RT*:%t2
-  %t3 = getelementptr %RT* %t2, uint 0, ubyte 1               ; yields [10 x [20 x int]]*:%t3
-  %t4 = getelementptr [10 x [20 x int]]* %t3, uint 0, uint 5  ; yields [20 x int]*:%t4
-  %t5 = getelementptr [20 x int]* %t4, uint 0, uint 13        ; yields int*:%t5
+  %t1 = getelementptr %ST* %s , long 1                        ; yields %ST*:%t1
+  %t2 = getelementptr %ST* %t1, long 0, ubyte 2               ; yields %RT*:%t2
+  %t3 = getelementptr %RT* %t2, long 0, ubyte 1               ; yields [10 x [20 x int]]*:%t3
+  %t4 = getelementptr [10 x [20 x int]]* %t3, long 0, long 5  ; yields [20 x int]*:%t4
+  %t5 = getelementptr [20 x int]* %t4, long 0, long 13        ; yields int*:%t5
   ret int* %t5
 }
 
@@ -1487,7 +1487,7 @@
Example:
   ; yields [12 x ubyte]*:aptr
-  %aptr = getelementptr {int, [12 x ubyte]}* %sptr, uint 0, ubyte 1
+  %aptr = getelementptr {int, [12 x ubyte]}* %sptr, long 0, ubyte 1
 
@@ -1706,7 +1706,7 @@
Chris Lattner
-Last modified: Mon Nov 4 18:20:38 CST 2002 +Last modified: Fri Dec 13 00:00:57 CST 2002 From lattner at cs.uiuc.edu Fri Dec 13 00:47:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 00:47:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp X86TargetMachine.cpp Message-ID: <200212130646.AAA14253@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.55 -> 1.56 X86TargetMachine.cpp updated: 1.3 -> 1.4 --- Log message: brg InstSelectSimple.cpp: Add stub implementation of visitFreeInst. Add comments that mention how we are failing to implement malloc/free. Add initial implementation of visitAllocaInst. X86TargetMachine.cpp: Include llvm/Transforms/Scalar.h. Add LowerAllocations pass before instruction selection. jello/Makefile: Add scalaropts.a. --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.55 llvm/lib/Target/X86/InstSelectSimple.cpp:1.56 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.55 Thu Dec 12 22:12:24 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 00:46:30 2002 @@ -101,6 +101,7 @@ void visitStoreInst(StoreInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); void visitMallocInst(MallocInst &I); + void visitFreeInst(FreeInst &I); void visitAllocaInst(AllocaInst &I); // Other operators @@ -885,6 +886,20 @@ void ISel::visitMallocInst (MallocInst &I) { + // We assume that by this point, malloc instructions have been + // lowered to calls, and dlsym will magically find malloc for us. + // So we do not want to see malloc instructions here. + visitInstruction (I); +} + + +/// visitFreeInst - same story as MallocInst +void +ISel::visitFreeInst (FreeInst &I) +{ + // We assume that by this point, free instructions have been + // lowered to calls, and dlsym will magically find free for us. + // So we do not want to see free instructions here. visitInstruction (I); } @@ -894,7 +909,18 @@ void ISel::visitAllocaInst (AllocaInst &I) { - visitInstruction (I); + // Find the data size of the alloca inst's getAllocatedType. + const Type *allocatedType = I.getAllocatedType (); + const TargetData &TD = TM.DataLayout; + unsigned allocatedTypeSize = TD.getTypeSize (allocatedType); + // Keep stack 32-bit aligned. + unsigned int allocatedTypeWords = allocatedTypeSize / 4; + if (allocatedTypeSize % 4 != 0) { allocatedTypeWords++; } + // Subtract size from stack pointer, thereby allocating some space. + BuildMI (BB, X86::SUBri32, 1, X86::ESP).addZImm (allocatedTypeWords * 4); + // Put a pointer to the space into the result register, by copying + // the stack pointer. + BuildMI (BB, X86::MOVrr32, 1, getReg (I)).addReg (X86::ESP); } Index: llvm/lib/Target/X86/X86TargetMachine.cpp diff -u llvm/lib/Target/X86/X86TargetMachine.cpp:1.3 llvm/lib/Target/X86/X86TargetMachine.cpp:1.4 --- llvm/lib/Target/X86/X86TargetMachine.cpp:1.3 Fri Nov 22 16:45:07 2002 +++ llvm/lib/Target/X86/X86TargetMachine.cpp Fri Dec 13 00:46:30 2002 @@ -5,6 +5,7 @@ //===----------------------------------------------------------------------===// #include "X86TargetMachine.h" +#include "llvm/Transforms/Scalar.h" #include "llvm/Target/TargetMachineImpls.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/PassManager.h" @@ -28,6 +29,11 @@ /// not supported for this target. /// bool X86TargetMachine::addPassesToJITCompile(PassManager &PM) { + // For the moment we have decided that malloc and free will be + // taken care of by converting them to calls, using the existing + // LLVM scalar transforms pass to do this. + PM.add(createLowerAllocationsPass()); + PM.add(createSimpleX86InstructionSelector(*this)); // TODO: optional optimizations go here From lattner at cs.uiuc.edu Fri Dec 13 00:47:06 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 00:47:06 2002 Subject: [llvm-commits] CVS: llvm/tools/jello/Makefile Message-ID: <200212130646.AAA14252@psmith.cs.uiuc.edu> Changes in directory llvm/tools/jello: Makefile updated: 1.2 -> 1.3 --- Log message: brg InstSelectSimple.cpp: Add stub implementation of visitFreeInst. Add comments that mention how we are failing to implement malloc/free. Add initial implementation of visitAllocaInst. X86TargetMachine.cpp: Include llvm/Transforms/Scalar.h. Add LowerAllocations pass before instruction selection. jello/Makefile: Add scalaropts.a. --- Diffs of the changes: Index: llvm/tools/jello/Makefile diff -u llvm/tools/jello/Makefile:1.2 llvm/tools/jello/Makefile:1.3 --- llvm/tools/jello/Makefile:1.2 Mon Nov 4 14:50:53 2002 +++ llvm/tools/jello/Makefile Fri Dec 13 00:46:31 2002 @@ -1,6 +1,6 @@ LEVEL = ../.. TOOLNAME = jello -USEDLIBS = bcreader vmcore codegen x86 support.a target.a +USEDLIBS = bcreader vmcore codegen x86 support.a target.a scalaropts.a # Have gcc tell the linker to export symbols from the program so that # dynamically loaded modules can be linked against them. From lattner at cs.uiuc.edu Fri Dec 13 00:57:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 00:57:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp X86RegisterClasses.cpp Message-ID: <200212130656.AAA02120@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.56 -> 1.57 X86RegisterClasses.cpp updated: 1.2 -> 1.3 --- Log message: Implement getelementptr constant exprs Implement ConstantPointerRefs Treat long/ulongs as if they were integers. A hack, but an effective one --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.56 llvm/lib/Target/X86/InstSelectSimple.cpp:1.57 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.56 Fri Dec 13 00:46:30 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 00:56:29 2002 @@ -114,8 +114,14 @@ abort(); } - void promote32 (const unsigned targetReg, Value *v); - + void promote32(unsigned targetReg, Value *V); + + // emitGEPOperation - Common code shared between visitGetElemenPtrInst and + // constant expression GEP support. + // + void emitGEPOperation(Value *Src, User::op_iterator IdxBegin, + User::op_iterator IdxEnd, unsigned TargetReg); + /// copyConstantToRegister - Output the instructions required to put the /// specified constant into the specified register. /// @@ -123,9 +129,10 @@ /// makeAnotherReg - This method returns the next register number /// we haven't yet used. - unsigned makeAnotherReg (void) { - unsigned Reg = CurReg++; - return Reg; + unsigned makeAnotherReg(const Type *Ty) { + // Add the mapping of regnumber => reg class to MachineFunction + F->addRegMap(CurReg, TM.getRegisterInfo()->getRegClassForType(Ty)); + return CurReg++; } /// getReg - This method turns an LLVM value into a register number. This @@ -136,12 +143,8 @@ unsigned getReg(Value *V) { unsigned &Reg = RegMap[V]; if (Reg == 0) { - Reg = makeAnotherReg (); + Reg = makeAnotherReg(V->getType()); RegMap[V] = Reg; - - // Add the mapping of regnumber => reg class to MachineFunction - F->addRegMap(Reg, - TM.getRegisterInfo()->getRegClassForType(V->getType())); } // If this operand is a constant, emit the code to copy the constant into @@ -182,7 +185,9 @@ case Type::PointerTyID: return cInt; // Int's and pointers are class #2 case Type::LongTyID: - case Type::ULongTyID: return cLong; // Longs are class #3 + case Type::ULongTyID: //return cLong; // Longs are class #3 + return cInt; // FIXME: LONGS ARE TREATED AS INTS! + case Type::FloatTyID: return cFloat; // Float is class #4 case Type::DoubleTyID: return cDouble; // Doubles are class #5 default: @@ -196,12 +201,15 @@ /// specified constant into the specified register. /// void ISel::copyConstantToRegister(Constant *C, unsigned R) { - if (isa (C)) { - // FIXME: We really need to handle getelementptr exprs, among - // other things. + if (ConstantExpr *CE = dyn_cast(C)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + emitGEPOperation(CE->getOperand(0), CE->op_begin()+1, CE->op_end(), R); + return; + } + std::cerr << "Offending expr: " << C << "\n"; + assert (0 && "Constant expressions not yet handled!\n"); } - assert (!isa(C) && "Constant expressions not yet handled!\n"); if (C->getType()->isIntegral()) { unsigned Class = getClass(C->getType()); @@ -221,6 +229,9 @@ } else if (isa (C)) { // Copy zero (null pointer) to the register. BuildMI (BB, X86::MOVir32, 1, R).addZImm(0); + } else if (ConstantPointerRef *CPR = dyn_cast(C)) { + unsigned SrcReg = getReg(CPR->getValue()); + BuildMI (BB, X86::MOVrr32, 1, R).addReg(SrcReg); } else { std::cerr << "Offending constant: " << C << "\n"; assert(0 && "Type not handled yet!"); @@ -305,7 +316,7 @@ /// promote32 - Emit instructions to turn a narrow operand into a 32-bit-wide /// operand, in the specified target register. void -ISel::promote32 (const unsigned targetReg, Value *v) +ISel::promote32 (unsigned targetReg, Value *v) { unsigned vReg = getReg (v); unsigned Class = getClass (v->getType ()); @@ -806,17 +817,21 @@ void ISel::visitGetElementPtrInst (GetElementPtrInst &I) { - Value *basePtr = I.getPointerOperand (); - const TargetData &TD = TM.DataLayout; - unsigned basePtrReg = getReg (basePtr); - unsigned resultReg = getReg (I); - const Type *Ty = basePtr->getType(); + emitGEPOperation(I.getOperand(0), I.op_begin()+1, I.op_end(), getReg(I)); +} + +void ISel::emitGEPOperation(Value *Src, User::op_iterator IdxBegin, + User::op_iterator IdxEnd, unsigned TargetReg) { + const TargetData &TD = TM.getTargetData(); + const Type *Ty = Src->getType(); + unsigned basePtrReg = getReg(Src); + // GEPs have zero or more indices; we must perform a struct access // or array access for each one. - for (GetElementPtrInst::op_iterator oi = I.idx_begin (), - oe = I.idx_end (); oi != oe; ++oi) { + for (GetElementPtrInst::op_iterator oi = IdxBegin, + oe = IdxEnd; oi != oe; ++oi) { Value *idx = *oi; - unsigned nextBasePtrReg = makeAnotherReg (); + unsigned nextBasePtrReg = makeAnotherReg(Type::UIntTy); if (const StructType *StTy = dyn_cast (Ty)) { // It's a struct access. idx is the index into the structure, // which names the field. This index must have ubyte type. @@ -839,10 +854,6 @@ Ty = StTy->getElementTypes ()[idxValue]; } else if (const SequentialType *SqTy = cast (Ty)) { // It's an array or pointer access: [ArraySize x ElementType]. - // The documentation does not seem to match the code on the type - // of array indices. The code seems to use long, and the docs - // (and the comments) say uint. If it is long, I don't know what - // we are going to do, because the X86 loves 64-bit types. const Type *typeOfSequentialTypeIndex = SqTy->getIndexType (); // idx is the index into the array. Unlike with structure // indices, we may not know its actual value at code-generation @@ -855,14 +866,14 @@ // elements in the array.) Ty = SqTy->getElementType (); unsigned elementSize = TD.getTypeSize (Ty); - unsigned elementSizeReg = makeAnotherReg (); + unsigned elementSizeReg = makeAnotherReg(Type::UIntTy); copyConstantToRegister (ConstantInt::get (typeOfSequentialTypeIndex, elementSize), elementSizeReg); unsigned idxReg = getReg (idx); // Emit a MUL to multiply the register holding the index by // elementSize, putting the result in memberOffsetReg. - unsigned memberOffsetReg = makeAnotherReg (); + unsigned memberOffsetReg = makeAnotherReg(Type::UIntTy); doMultiply (memberOffsetReg, typeOfSequentialTypeIndex, elementSizeReg, idxReg); // Emit an ADD to add memberOffsetReg to the basePtr. @@ -877,7 +888,7 @@ // basePtrReg. Move it to the register where we were expected to // put the answer. A 32-bit move should do it, because we are in // ILP32 land. - BuildMI (BB, X86::MOVrr32, 1, getReg (I)).addReg (basePtrReg); + BuildMI (BB, X86::MOVrr32, 1, TargetReg).addReg (basePtrReg); } Index: llvm/lib/Target/X86/X86RegisterClasses.cpp diff -u llvm/lib/Target/X86/X86RegisterClasses.cpp:1.2 llvm/lib/Target/X86/X86RegisterClasses.cpp:1.3 --- llvm/lib/Target/X86/X86RegisterClasses.cpp:1.2 Wed Nov 20 18:25:56 2002 +++ llvm/lib/Target/X86/X86RegisterClasses.cpp Fri Dec 13 00:56:29 2002 @@ -106,12 +106,13 @@ case Type::UByteTyID: return &X86ByteRegisterClassInstance; case Type::ShortTyID: case Type::UShortTyID: return &X86ShortRegisterClassInstance; + case Type::LongTyID: // None of these are handled yet! + case Type::ULongTyID: // FIXME: Treat these like ints, this is bogus! + case Type::IntTyID: case Type::UIntTyID: case Type::PointerTyID: return &X86IntRegisterClassInstance; - case Type::LongTyID: /* None of these are handled yet! */ - case Type::ULongTyID: case Type::FloatTyID: case Type::DoubleTyID: From lattner at cs.uiuc.edu Fri Dec 13 00:58:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 00:58:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/hello.ll Message-ID: <200212130657.AAA02320@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: hello.ll updated: 1.1 -> 1.2 --- Log message: return 0 on success --- Diffs of the changes: Index: llvm/test/Regression/Jello/hello.ll diff -u llvm/test/Regression/Jello/hello.ll:1.1 llvm/test/Regression/Jello/hello.ll:1.2 --- llvm/test/Regression/Jello/hello.ll:1.1 Tue Dec 3 14:25:43 2002 +++ llvm/test/Regression/Jello/hello.ll Fri Dec 13 00:57:24 2002 @@ -4,8 +4,8 @@ declare int %puts(sbyte*) -void %main() { +int %main() { %reg210 = call int %puts( sbyte* getelementptr ([12 x sbyte]* %.LC0, long 0, long 0) ) - ret void + ret int 0 } From lattner at cs.uiuc.edu Fri Dec 13 01:31:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 01:31:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineBasicBlock.h Message-ID: <200212130730.BAA07281@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineBasicBlock.h updated: 1.9 -> 1.10 --- Log message: Get rid of deprecated function --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineBasicBlock.h diff -u llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.9 llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.10 --- llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.9 Sun Oct 27 23:30:41 2002 +++ llvm/include/llvm/CodeGen/MachineBasicBlock.h Fri Dec 13 01:30:45 2002 @@ -20,11 +20,6 @@ MachineBasicBlock(BasicBlock *bb = 0) : Prev(0), Next(0), BB(bb) {} ~MachineBasicBlock() {} - // get - This deprecated static method returns the MachineBasicBlock object - // for the specified BasicBlock. - // - static MachineBasicBlock& get(const BasicBlock *BB); - /// getBasicBlock - Return the LLVM basic block that this instance /// corresponded to originally. /// From lattner at cs.uiuc.edu Fri Dec 13 01:57:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 01:57:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp MachineCodeEmitter.cpp Printer.cpp Message-ID: <200212130756.BAA14335@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.57 -> 1.58 MachineCodeEmitter.cpp updated: 1.10 -> 1.11 Printer.cpp updated: 1.25 -> 1.26 --- Log message: InstSelectSimple.cpp: Give promote32 a comment. Add initial implementation of getReg() for arguments. MachineCodeEmitter.cpp: Fix using EBP with index, scale and no displacement (whew!) due to Chris. Printer.cpp: Fix printing out index and scale in memory references. --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.57 llvm/lib/Target/X86/InstSelectSimple.cpp:1.58 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.57 Fri Dec 13 00:56:29 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 01:56:18 2002 @@ -114,9 +114,10 @@ abort(); } - void promote32(unsigned targetReg, Value *V); - - // emitGEPOperation - Common code shared between visitGetElemenPtrInst and + /// promote32 - Make a value 32-bits wide, and put it somewhere. + void promote32 (const unsigned targetReg, Value *v); + + // emitGEPOperation - Common code shared between visitGetElementPtrInst and // constant expression GEP support. // void emitGEPOperation(Value *Src, User::op_iterator IdxBegin, @@ -156,7 +157,25 @@ // Move the address of the global into the register BuildMI(BB, X86::MOVir32, 1, Reg).addReg(GV); } else if (Argument *A = dyn_cast(V)) { - std::cerr << "ERROR: Arguments not implemented in SimpleInstSel\n"; + // Find the position of the argument in the argument list. + const Function *f = F->getFunction (); + int counter = 0, argPosition = -1; + for (Function::const_aiterator ai = f->abegin (), ae = f->aend (); + ai != ae; ++ai) { + ++counter; + if (&(*ai) == A) { + argPosition = counter; + } + } + assert (argPosition != -1 + && "Argument not found in current function's argument list"); + // Load it out of the stack frame at EBP + 4*argPosition. + // (First, load Reg with argPosition, then load Reg with DWORD + // PTR [EBP + 4*Reg].) + BuildMI (BB, X86::MOVir32, 1, Reg).addZImm (argPosition); + BuildMI (BB, X86::MOVmr32, 4, + Reg).addReg (X86::EBP).addZImm (4).addReg (Reg).addSImm (0); + // std::cerr << "ERROR: Arguments not implemented in SimpleInstSel\n"; } return Reg; Index: llvm/lib/Target/X86/MachineCodeEmitter.cpp diff -u llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.10 llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.11 --- llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.10 Thu Dec 12 23:05:05 2002 +++ llvm/lib/Target/X86/MachineCodeEmitter.cpp Fri Dec 13 01:56:18 2002 @@ -157,17 +157,19 @@ assert(IndexReg.getReg() != X86::ESP && "Cannot use ESP as index reg!"); bool ForceDisp32 = false; + bool ForceDisp8 = false; if (BaseReg.getReg() == 0) { // If there is no base register, we emit the special case SIB byte with // MOD=0, BASE=5, to JUST get the index, scale, and displacement. MCE.emitByte(ModRMByte(0, RegOpcodeField, 4)); ForceDisp32 = true; - } else if (Disp.getImmedValue() == 0) { + } else if (Disp.getImmedValue() == 0 && BaseReg.getReg() != X86::EBP) { // Emit no displacement ModR/M byte MCE.emitByte(ModRMByte(0, RegOpcodeField, 4)); } else if (isDisp8(Disp.getImmedValue())) { // Emit the disp8 encoding... MCE.emitByte(ModRMByte(1, RegOpcodeField, 4)); + ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP } else { // Emit the normal disp32 encoding... MCE.emitByte(ModRMByte(2, RegOpcodeField, 4)); @@ -189,7 +191,7 @@ } // Do we need to output a displacement? - if (Disp.getImmedValue() != 0 || ForceDisp32) { + if (Disp.getImmedValue() != 0 || ForceDisp32 || ForceDisp8) { if (!ForceDisp32 && isDisp8(Disp.getImmedValue())) emitConstant(Disp.getImmedValue(), 1); else Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.25 llvm/lib/Target/X86/Printer.cpp:1.26 --- llvm/lib/Target/X86/Printer.cpp:1.25 Thu Dec 12 21:51:55 2002 +++ llvm/lib/Target/X86/Printer.cpp Fri Dec 13 01:56:18 2002 @@ -148,8 +148,8 @@ if (IndexReg.getReg()) { if (NeedPlus) O << " + "; - if (IndexReg.getImmedValue() != 1) - O << IndexReg.getImmedValue() << "*"; + if (Scale.getImmedValue() != 1) + O << Scale.getImmedValue() << "*"; printOp(O, IndexReg, RI); NeedPlus = true; } From lattner at cs.uiuc.edu Fri Dec 13 03:29:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 03:29:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-loadstore.ll Message-ID: <200212130929.DAA14440@psmith.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-loadstore.ll updated: 1.2 -> 1.3 --- Log message: lib/Target/X86/InstSelectSimple.cpp: Start counting arguments with 2, because arguments start two stack slots off of EBP. Break out of the for loop once the argument is found. Increment the counter at the end of the loop instead of the beginning. Use addRegOffset and compute the scale * index part at compile time instead of using the fancy load instruction. Just because an instruction set has wacky addressing modes doesn't mean we ought to use them (at least, if you believe Dave Patterson). lib/Target/X86/X86InstrBuilder.h: Add some comments. test/Regression/Jello/test-loadstore.ll: Let main return int 0. --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-loadstore.ll diff -u llvm/test/Regression/Jello/test-loadstore.ll:1.2 llvm/test/Regression/Jello/test-loadstore.ll:1.3 --- llvm/test/Regression/Jello/test-loadstore.ll:1.2 Wed Dec 4 11:15:07 2002 +++ llvm/test/Regression/Jello/test-loadstore.ll Fri Dec 13 03:28:50 2002 @@ -11,10 +11,10 @@ ret void } -void %main() { +int %main() { %A = alloca sbyte %B = alloca short %C = alloca int call void %test(sbyte* %A, short* %B, int* %C) - ret void + ret int 0 } From lattner at cs.uiuc.edu Fri Dec 13 03:29:04 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 03:29:04 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp X86InstrBuilder.h Message-ID: <200212130929.DAA14439@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.58 -> 1.59 X86InstrBuilder.h updated: 1.2 -> 1.3 --- Log message: lib/Target/X86/InstSelectSimple.cpp: Start counting arguments with 2, because arguments start two stack slots off of EBP. Break out of the for loop once the argument is found. Increment the counter at the end of the loop instead of the beginning. Use addRegOffset and compute the scale * index part at compile time instead of using the fancy load instruction. Just because an instruction set has wacky addressing modes doesn't mean we ought to use them (at least, if you believe Dave Patterson). lib/Target/X86/X86InstrBuilder.h: Add some comments. test/Regression/Jello/test-loadstore.ll: Let main return int 0. --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.58 llvm/lib/Target/X86/InstSelectSimple.cpp:1.59 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.58 Fri Dec 13 01:56:18 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 03:28:50 2002 @@ -159,23 +159,24 @@ } else if (Argument *A = dyn_cast(V)) { // Find the position of the argument in the argument list. const Function *f = F->getFunction (); - int counter = 0, argPosition = -1; + // The function's arguments look like this: + // [EBP] -- copy of old EBP + // [EBP + 4] -- return address + // [EBP + 8] -- first argument (leftmost lexically) + // So we want to start with counter = 2. + int counter = 2, argPosition = -1; for (Function::const_aiterator ai = f->abegin (), ae = f->aend (); ai != ae; ++ai) { - ++counter; if (&(*ai) == A) { argPosition = counter; + break; // Only need to find it once. ;-) } + ++counter; } assert (argPosition != -1 && "Argument not found in current function's argument list"); // Load it out of the stack frame at EBP + 4*argPosition. - // (First, load Reg with argPosition, then load Reg with DWORD - // PTR [EBP + 4*Reg].) - BuildMI (BB, X86::MOVir32, 1, Reg).addZImm (argPosition); - BuildMI (BB, X86::MOVmr32, 4, - Reg).addReg (X86::EBP).addZImm (4).addReg (Reg).addSImm (0); - // std::cerr << "ERROR: Arguments not implemented in SimpleInstSel\n"; + addRegOffset (BuildMI (BB, X86::MOVmr32, 4, Reg), X86::EBP, 4*argPosition); } return Reg; Index: llvm/lib/Target/X86/X86InstrBuilder.h diff -u llvm/lib/Target/X86/X86InstrBuilder.h:1.2 llvm/lib/Target/X86/X86InstrBuilder.h:1.3 --- llvm/lib/Target/X86/X86InstrBuilder.h:1.2 Fri Nov 22 16:42:12 2002 +++ llvm/lib/Target/X86/X86InstrBuilder.h Fri Dec 13 03:28:50 2002 @@ -9,6 +9,9 @@ // up behind an easier to use interface makes sense. Descriptions of the // functions are included below. // +// For reference, the order of operands for memory references is: +// (Operand), Base, Scale, Index, Displacement. +// //===----------------------------------------------------------------------===// #ifndef X86INSTRBUILDER_H @@ -17,18 +20,19 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" /// addDirectMem - This function is used to add a direct memory reference to the -/// current instruction. Because memory references are always represented with -/// four values, this adds: Reg, [1, NoReg, 0] to the instruction -/// +/// current instruction -- that is, a dereference of an address in a register, with +/// no scale, index or displacement. An example is: DWORD PTR [EAX]. inline const MachineInstrBuilder &addDirectMem(const MachineInstrBuilder &MIB, unsigned Reg) { + // Because memory references are always represented with four + // values, this adds: Reg, [1, NoReg, 0] to the instruction. return MIB.addReg(Reg).addZImm(1).addMReg(0).addSImm(0); } -/// addRegOffset - -/// -/// +/// addRegOffset - This function is used to add a memory reference of +/// the form [Reg + Offset], i.e., one with no scale or index, but +/// with a displacement. An example is: DWORD PTR [EAX + 4]. inline const MachineInstrBuilder &addRegOffset(const MachineInstrBuilder &MIB, unsigned Reg, unsigned Offset) { return MIB.addReg(Reg).addZImm(1).addMReg(0).addSImm(Offset); From lattner at cs.uiuc.edu Fri Dec 13 03:34:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 03:34:00 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineInstrBuilder.h Message-ID: <200212130933.DAA13051@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineInstrBuilder.h updated: 1.7 -> 1.8 --- Log message: Final version of BuildMI for symmetry and because I want to use it --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineInstrBuilder.h diff -u llvm/include/llvm/CodeGen/MachineInstrBuilder.h:1.7 llvm/include/llvm/CodeGen/MachineInstrBuilder.h:1.8 --- llvm/include/llvm/CodeGen/MachineInstrBuilder.h:1.7 Sun Nov 17 15:56:10 2002 +++ llvm/include/llvm/CodeGen/MachineInstrBuilder.h Fri Dec 13 03:33:06 2002 @@ -91,6 +91,17 @@ return MachineInstrBuilder(new MachineInstr(Opcode, NumOperands, true, true)); } +/// BuildMI - This version of the builder also sets up the first "operand" as a +/// destination virtual register. NumOperands is the number of additional add* +/// calls that are expected, it does not include the destination register. +/// +inline MachineInstrBuilder BuildMI(MachineOpCode Opcode, unsigned NumOperands, + unsigned DestReg) { + return MachineInstrBuilder(new MachineInstr(Opcode, NumOperands+1, + true, true)).addReg(DestReg, MOTy::Def); +} + + /// BuildMI - This version of the builder inserts the built MachineInstr into /// the specified MachineBasicBlock. /// From brukman at cs.uiuc.edu Fri Dec 13 03:55:00 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 03:55:00 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200212130954.DAA15277@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.7 -> 1.8 --- Log message: Added moveReg2Reg() and moveImm2Reg() to accomodate moving data around due to PHI nodes. --- Diffs of the changes: Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.7 llvm/include/llvm/Target/MRegisterInfo.h:1.8 --- llvm/include/llvm/Target/MRegisterInfo.h:1.7 Wed Dec 4 17:55:56 2002 +++ llvm/include/llvm/Target/MRegisterInfo.h Fri Dec 13 03:54:10 2002 @@ -130,6 +130,16 @@ unsigned ImmOffset, unsigned dataSize) const = 0; virtual MachineBasicBlock::iterator + moveReg2Reg(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned SrcReg, unsigned dataSize) const = 0; + + virtual MachineBasicBlock::iterator + moveImm2Reg(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned Imm, unsigned dataSize) const = 0; + + virtual MachineBasicBlock::iterator emitPrologue(MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI, unsigned numBytes) const = 0; From brukman at cs.uiuc.edu Fri Dec 13 03:55:02 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 03:55:02 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp X86RegisterInfo.h Message-ID: <200212130954.DAA15286@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.10 -> 1.11 X86RegisterInfo.h updated: 1.7 -> 1.8 --- Log message: Added moveReg2Reg() and moveImm2Reg() to accomodate moving data around due to PHI nodes. --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.10 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.11 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.10 Thu Dec 12 22:24:53 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Fri Dec 13 03:54:12 2002 @@ -63,6 +63,42 @@ return ++(MBB->insert(MBBI, MI)); } +MachineBasicBlock::iterator +X86RegisterInfo::moveReg2Reg(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned SrcReg, + unsigned dataSize) const +{ + unsigned opcode; + switch (dataSize) { + case 1: opcode = X86::MOVrr8; break; + case 2: opcode = X86::MOVrr16; break; + case 4: opcode = X86::MOVrr32; break; + default: assert(0 && "Invalid data size!"); + } + + MachineInstr *MI = BuildMI(opcode, 2).addReg(DestReg).addReg(SrcReg); + return ++(MBB->insert(MBBI, MI)); +} + +MachineBasicBlock::iterator +X86RegisterInfo::moveImm2Reg(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned Imm, unsigned dataSize) + const +{ + unsigned opcode; + switch (dataSize) { + case 1: opcode = X86::MOVir8; break; + case 2: opcode = X86::MOVir16; break; + case 4: opcode = X86::MOVir32; break; + default: assert(0 && "Invalid data size!"); + } + + MachineInstr *MI = BuildMI(opcode, 2).addReg(DestReg).addReg(Imm); + return ++(MBB->insert(MBBI, MI)); +} + unsigned X86RegisterInfo::getFramePointer() const { return X86::EBP; Index: llvm/lib/Target/X86/X86RegisterInfo.h diff -u llvm/lib/Target/X86/X86RegisterInfo.h:1.7 llvm/lib/Target/X86/X86RegisterInfo.h:1.8 --- llvm/lib/Target/X86/X86RegisterInfo.h:1.7 Wed Dec 4 17:57:03 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.h Fri Dec 13 03:54:12 2002 @@ -29,6 +29,16 @@ unsigned DestReg, unsigned SrcReg, unsigned ImmOffset, unsigned dataSize) const; + MachineBasicBlock::iterator + moveReg2Reg(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned SrcReg, unsigned dataSize) const; + + MachineBasicBlock::iterator + moveImm2Reg(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned Imm, unsigned dataSize) const; + unsigned getFramePointer() const; unsigned getStackPointer() const; From brukman at cs.uiuc.edu Fri Dec 13 03:55:04 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 03:55:04 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212130954.DAA15306@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.7 -> 1.8 --- Log message: This should handle register allocating PHI nodes. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.7 llvm/lib/CodeGen/RegAllocSimple.cpp:1.8 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.7 Thu Dec 12 22:34:02 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Fri Dec 13 03:54:36 2002 @@ -20,7 +20,7 @@ #include "Support/Statistic.h" #include -namespace { +//namespace { struct RegAllocSimple : public FunctionPass { TargetMachine &TM; MachineBasicBlock *CurrMBB; @@ -82,21 +82,24 @@ void cleanupAfterFunction() { RegMap.clear(); SSA2PhysRegMap.clear(); - NumBytesAllocated = 4; + NumBytesAllocated = ByteAlignment; } /// Moves value from memory into that register MachineBasicBlock::iterator - moveUseToReg (MachineBasicBlock::iterator I, unsigned VirtReg, + moveUseToReg (MachineBasicBlock *MBB, + MachineBasicBlock::iterator I, unsigned VirtReg, unsigned &PhysReg); /// Saves reg value on the stack (maps virtual register to stack value) MachineBasicBlock::iterator - saveVirtRegToStack (MachineBasicBlock::iterator I, unsigned VirtReg, + saveVirtRegToStack (MachineBasicBlock *MBB, + MachineBasicBlock::iterator I, unsigned VirtReg, unsigned PhysReg); MachineBasicBlock::iterator - savePhysRegToStack (MachineBasicBlock::iterator I, unsigned PhysReg); + savePhysRegToStack (MachineBasicBlock *MBB, + MachineBasicBlock::iterator I, unsigned PhysReg); /// runOnFunction - Top level implementation of instruction selection for /// the entire function. @@ -108,7 +111,7 @@ } }; -} +//} unsigned RegAllocSimple::allocateStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *regClass) @@ -126,7 +129,7 @@ #endif // FIXME: forcing each arg to take 4 bytes on the stack RegMap[VirtReg] = NumBytesAllocated; - NumBytesAllocated += 4; + NumBytesAllocated += ByteAlignment; } return RegMap[VirtReg]; } @@ -153,7 +156,8 @@ } MachineBasicBlock::iterator -RegAllocSimple::moveUseToReg (MachineBasicBlock::iterator I, +RegAllocSimple::moveUseToReg (MachineBasicBlock *MBB, + MachineBasicBlock::iterator I, unsigned VirtReg, unsigned &PhysReg) { const TargetRegisterClass* regClass = MF->getRegClass(VirtReg); @@ -162,16 +166,15 @@ unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass); PhysReg = getFreeReg(VirtReg); - // FIXME: increment the frame pointer - // Add move instruction(s) - return RegInfo->loadRegOffset2Reg(CurrMBB, I, PhysReg, + return RegInfo->loadRegOffset2Reg(MBB, I, PhysReg, RegInfo->getFramePointer(), -stackOffset, regClass->getDataSize()); } MachineBasicBlock::iterator -RegAllocSimple::saveVirtRegToStack (MachineBasicBlock::iterator I, +RegAllocSimple::saveVirtRegToStack (MachineBasicBlock *MBB, + MachineBasicBlock::iterator I, unsigned VirtReg, unsigned PhysReg) { const TargetRegisterClass* regClass = MF->getRegClass(VirtReg); @@ -180,13 +183,14 @@ unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass); // Add move instruction(s) - return RegInfo->storeReg2RegOffset(CurrMBB, I, PhysReg, + return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(), -stackOffset, regClass->getDataSize()); } MachineBasicBlock::iterator -RegAllocSimple::savePhysRegToStack (MachineBasicBlock::iterator I, +RegAllocSimple::savePhysRegToStack (MachineBasicBlock *MBB, + MachineBasicBlock::iterator I, unsigned PhysReg) { const TargetRegisterClass* regClass = MF->getRegClass(PhysReg); @@ -195,7 +199,7 @@ unsigned offset = allocateStackSpaceFor(PhysReg, regClass); // Add move instruction(s) - return RegInfo->storeReg2RegOffset(CurrMBB, I, PhysReg, + return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(), offset, regClass->getDataSize()); } @@ -212,20 +216,90 @@ { CurrMBB = &(*MBB); + // Handle PHI instructions specially: add moves to each pred block + while (MBB->front()->getOpcode() == 0) { + MachineInstr *MI = MBB->front(); + // get rid of the phi + MBB->erase(MBB->begin()); + + DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n"); + MachineOperand &targetReg = MI->getOperand(0); + + // If it's a virtual register, allocate a physical one + // otherwise, just use whatever register is there now + // note: it MUST be a register -- we're assigning to it + virtualReg = (unsigned) targetReg.getAllocatedRegNum(); + if (targetReg.isVirtualRegister()) { + physReg = getFreeReg(virtualReg); + } else { + physReg = targetReg.getAllocatedRegNum(); + } + + // Find the register class of the target register: should be the + // same as the values we're trying to store there + const TargetRegisterClass* regClass = PhysReg2RegClassMap[physReg]; + assert(regClass && "Target register class not found!"); + unsigned dataSize = regClass->getDataSize(); + + for (int i = MI->getNumOperands() - 1; i >= 2; i-=2) { + MachineOperand &opVal = MI->getOperand(i-1); + + // Get the MachineBasicBlock equivalent of the BasicBlock that is the + // source path the phi + BasicBlock *opBB = + cast(MI->getOperand(i).getVRegValue()); + MachineBasicBlock *opBlock = NULL; + for (MachineFunction::iterator opFi = Fn.begin(), opFe = Fn.end(); + opFi != opFe; ++opFi) + { + if (opFi->getBasicBlock() == opBB) { + opBlock = opFi; break; + } + } + assert(opBlock && "MachineBasicBlock object not found for specified block!"); + + MachineBasicBlock::iterator opI = opBlock->end(); + MachineInstr *opMI = *(--opI); + const MachineInstrInfo &MII = TM.getInstrInfo(); + + // insert the move just before the return/branch + if (MII.isReturn(opMI->getOpcode()) || MII.isBranch(opMI->getOpcode())) + { + // Retrieve the constant value from this op, move it to target + // register of the phi + if (opVal.getType() == MachineOperand::MO_SignExtendedImmed || + opVal.getType() == MachineOperand::MO_UnextendedImmed) + { + opI = RegInfo->moveImm2Reg(opBlock, opI, physReg, + (unsigned) opVal.getImmedValue(), + dataSize); + saveVirtRegToStack(opBlock, opI, virtualReg, physReg); + } else { + // Allocate a physical register and add a move in the BB + unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum(); + unsigned opPhysReg; // = getFreeReg(opVirtualReg); + opI = moveUseToReg(opBlock, opI, opVirtualReg, opPhysReg); + opI = RegInfo->moveReg2Reg(opBlock, opI, physReg, opPhysReg, + dataSize); + // Save that register value to the stack of the TARGET REG + saveVirtRegToStack(opBlock, opI, virtualReg, opPhysReg); + } + } + } + + // really delete the instruction + delete MI; + } + //loop over each basic block for (MachineBasicBlock::iterator I = MBB->begin(); I != MBB->end(); ++I) { MachineInstr *MI = *I; - DEBUG(std::cerr << "instr: "; - MI->print(std::cerr, TM)); - // FIXME: add a preliminary pass that will invalidate any registers that // are used by the instruction (including implicit uses) - - // Loop over each instruction: - // uses, move from memory into registers + // Loop over uses, move from memory into registers for (int i = MI->getNumOperands() - 1; i >= 0; --i) { MachineOperand &op = MI->getOperand(i); @@ -253,10 +327,10 @@ physReg = getFreeReg(virtualReg); } MachineBasicBlock::iterator J = I; - J = saveVirtRegToStack(++J, virtualReg, physReg); + J = saveVirtRegToStack(CurrMBB, ++J, virtualReg, physReg); I = --J; } else { - I = moveUseToReg(I, virtualReg, physReg); + I = moveUseToReg(CurrMBB, I, virtualReg, physReg); } VirtReg2PhysRegMap[virtualReg] = physReg; } From lattner at cs.uiuc.edu Fri Dec 13 04:00:02 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 04:00:02 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Printer.cpp Message-ID: <200212130959.DAA15527@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Printer.cpp updated: 1.26 -> 1.27 --- Log message: Print X86 PHI nodes in a sane manner --- Diffs of the changes: Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.26 llvm/lib/Target/X86/Printer.cpp:1.27 --- llvm/lib/Target/X86/Printer.cpp:1.26 Fri Dec 13 01:56:18 2002 +++ llvm/lib/Target/X86/Printer.cpp Fri Dec 13 03:59:26 2002 @@ -167,6 +167,22 @@ unsigned Opcode = MI->getOpcode(); const MachineInstrDescriptor &Desc = get(Opcode); + if (Opcode == X86::PHI) { + printOp(O, MI->getOperand(0), RI); + O << " = phi "; + for (unsigned i = 1, e = MI->getNumOperands(); i != e; i+=2) { + if (i != 1) O << ", "; + O << "["; + printOp(O, MI->getOperand(i), RI); + O << ", "; + printOp(O, MI->getOperand(i+1), RI); + O << "]"; + } + O << "\n"; + return; + } + + switch (Desc.TSFlags & X86II::FormMask) { case X86II::RawFrm: // The accepted forms of Raw instructions are: From lattner at cs.uiuc.edu Fri Dec 13 04:11:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 04:11:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212131010.EAA16738@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.59 -> 1.60 --- Log message: Code gen phi's correctly --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.59 llvm/lib/Target/X86/InstSelectSimple.cpp:1.60 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.59 Fri Dec 13 03:28:50 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 04:09:43 2002 @@ -26,6 +26,20 @@ using namespace MOTy; // Get Use, Def, UseAndDef + +/// BMI - A special BuildMI variant that takes an iterator to insert the +/// instruction at as well as a basic block. +inline static MachineInstrBuilder BMI(MachineBasicBlock *BB, + MachineBasicBlock::iterator &I, + MachineOpCode Opcode, + unsigned NumOperands, + unsigned DestReg) { + MachineInstr *MI = new MachineInstr(Opcode, NumOperands+1, true, true); + I = ++BB->insert(I, MI); + return MachineInstrBuilder(MI).addReg(DestReg, MOTy::Def); +} + + namespace { struct ISel : public FunctionPass, InstVisitor { TargetMachine &TM; @@ -35,6 +49,9 @@ unsigned CurReg; std::map RegMap; // Mapping between Val's and SSA Regs + // MBBMap - Mapping between LLVM BB -> Machine BB + std::map MBBMap; + ISel(TargetMachine &tm) : TM(tm), F(0), BB(0), CurReg(MRegisterInfo::FirstVirtualRegister) {} @@ -43,8 +60,18 @@ /// bool runOnFunction(Function &Fn) { F = &MachineFunction::construct(&Fn, TM); + + for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) + F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I)); + + // Instruction select everything except PHI nodes visit(Fn); + + // Select the PHI nodes + SelectPHINodes(); + RegMap.clear(); + MBBMap.clear(); CurReg = MRegisterInfo::FirstVirtualRegister; F = 0; return false; // We never modify the LLVM itself. @@ -56,11 +83,16 @@ /// instructions will be invoked for all instructions in the basic block. /// void visitBasicBlock(BasicBlock &LLVM_BB) { - BB = new MachineBasicBlock(&LLVM_BB); - // FIXME: Use the auto-insert form when it's available - F->getBasicBlockList().push_back(BB); + BB = MBBMap[&LLVM_BB]; } + + /// SelectPHINodes - Insert machine code to generate phis. This is tricky + /// because we have to generate our sources into the source basic blocks, + /// not the current one. + /// + void SelectPHINodes(); + // Visitation methods for various instructions. These methods simply emit // fixed X86 code for each instruction. // @@ -106,7 +138,7 @@ // Other operators void visitShiftInst(ShiftInst &I); - void visitPHINode(PHINode &I); + void visitPHINode(PHINode &I) {} // PHI nodes handled by second pass void visitCastInst(CastInst &I); void visitInstruction(Instruction &I) { @@ -120,13 +152,16 @@ // emitGEPOperation - Common code shared between visitGetElementPtrInst and // constant expression GEP support. // - void emitGEPOperation(Value *Src, User::op_iterator IdxBegin, + void emitGEPOperation(MachineBasicBlock *BB, MachineBasicBlock::iterator IP, + Value *Src, User::op_iterator IdxBegin, User::op_iterator IdxEnd, unsigned TargetReg); /// copyConstantToRegister - Output the instructions required to put the /// specified constant into the specified register. /// - void copyConstantToRegister(Constant *C, unsigned Reg); + void copyConstantToRegister(Constant *C, unsigned Reg, + MachineBasicBlock *MBB, + MachineBasicBlock::iterator MBBI); /// makeAnotherReg - This method returns the next register number /// we haven't yet used. @@ -141,7 +176,15 @@ /// every time it is queried. /// unsigned getReg(Value &V) { return getReg(&V); } // Allow references - unsigned getReg(Value *V) { + unsigned getReg(Value *V, MachineBasicBlock *BB = 0) { + MachineBasicBlock::iterator IPt; + if (BB == 0) { // Should we just append to the end of the current bb? + BB = this->BB; + IPt = BB->end(); + } else { // Otherwise, insert before the branch or ret instr... + IPt = BB->end()-1; + } + unsigned &Reg = RegMap[V]; if (Reg == 0) { Reg = makeAnotherReg(V->getType()); @@ -152,10 +195,10 @@ // the register here... // if (Constant *C = dyn_cast(V)) { - copyConstantToRegister(C, Reg); + copyConstantToRegister(C, Reg, BB, IPt); } else if (GlobalValue *GV = dyn_cast(V)) { // Move the address of the global into the register - BuildMI(BB, X86::MOVir32, 1, Reg).addReg(GV); + BMI(BB, IPt, X86::MOVir32, 1, Reg).addReg(GV); } else if (Argument *A = dyn_cast(V)) { // Find the position of the argument in the argument list. const Function *f = F->getFunction (); @@ -164,19 +207,19 @@ // [EBP + 4] -- return address // [EBP + 8] -- first argument (leftmost lexically) // So we want to start with counter = 2. - int counter = 2, argPosition = -1; + int counter = 2, argPos = -1; for (Function::const_aiterator ai = f->abegin (), ae = f->aend (); ai != ae; ++ai) { if (&(*ai) == A) { - argPosition = counter; + argPos = counter; break; // Only need to find it once. ;-) } ++counter; } - assert (argPosition != -1 + assert (argPos != -1 && "Argument not found in current function's argument list"); - // Load it out of the stack frame at EBP + 4*argPosition. - addRegOffset (BuildMI (BB, X86::MOVmr32, 4, Reg), X86::EBP, 4*argPosition); + // Load it out of the stack frame at EBP + 4*argPos. + addRegOffset(BMI(BB, IPt, X86::MOVmr32, 4, Reg), X86::EBP, 4*argPos); } return Reg; @@ -220,10 +263,13 @@ /// copyConstantToRegister - Output the instructions required to put the /// specified constant into the specified register. /// -void ISel::copyConstantToRegister(Constant *C, unsigned R) { +void ISel::copyConstantToRegister(Constant *C, unsigned R, + MachineBasicBlock *BB, + MachineBasicBlock::iterator IP) { if (ConstantExpr *CE = dyn_cast(C)) { if (CE->getOpcode() == Instruction::GetElementPtr) { - emitGEPOperation(CE->getOperand(0), CE->op_begin()+1, CE->op_end(), R); + emitGEPOperation(BB, IP, CE->getOperand(0), + CE->op_begin()+1, CE->op_end(), R); return; } @@ -241,23 +287,57 @@ if (C->getType()->isSigned()) { ConstantSInt *CSI = cast(C); - BuildMI(BB, IntegralOpcodeTab[Class], 1, R).addSImm(CSI->getValue()); + BMI(BB, IP, IntegralOpcodeTab[Class], 1, R).addSImm(CSI->getValue()); } else { ConstantUInt *CUI = cast(C); - BuildMI(BB, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue()); + BMI(BB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue()); } } else if (isa (C)) { // Copy zero (null pointer) to the register. - BuildMI (BB, X86::MOVir32, 1, R).addZImm(0); + BMI(BB, IP, X86::MOVir32, 1, R).addZImm(0); } else if (ConstantPointerRef *CPR = dyn_cast(C)) { unsigned SrcReg = getReg(CPR->getValue()); - BuildMI (BB, X86::MOVrr32, 1, R).addReg(SrcReg); + BMI(BB, IP, X86::MOVrr32, 1, R).addReg(SrcReg); } else { std::cerr << "Offending constant: " << C << "\n"; assert(0 && "Type not handled yet!"); } } +/// SelectPHINodes - Insert machine code to generate phis. This is tricky +/// because we have to generate our sources into the source basic blocks, not +/// the current one. +/// +void ISel::SelectPHINodes() { + const Function &LF = *F->getFunction(); // The LLVM function... + for (Function::const_iterator I = LF.begin(), E = LF.end(); I != E; ++I) { + const BasicBlock *BB = I; + MachineBasicBlock *MBB = MBBMap[I]; + + // Loop over all of the PHI nodes in the LLVM basic block... + unsigned NumPHIs = 0; + for (BasicBlock::const_iterator I = BB->begin(); + PHINode *PN = (PHINode*)dyn_cast(&*I); ++I) { + // Create a new machine instr PHI node, and insert it. + MachineInstr *MI = BuildMI(X86::PHI, PN->getNumOperands(), getReg(*PN)); + MBB->insert(MBB->begin()+NumPHIs++, MI); // Insert it at the top of the BB + + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + MachineBasicBlock *PredMBB = MBBMap[PN->getIncomingBlock(i)]; + + // Get the incoming value into a virtual register. If it is not already + // available in a virtual register, insert the computation code into + // PredMBB + MI->addRegOperand(getReg(PN->getIncomingValue(i), PredMBB)); + + // FIXME: Pass in the MachineBasicBlocks instead of the basic blocks... + MI->addPCDispOperand(PN->getIncomingBlock(i)); // PredMBB + } + } + } +} + + /// SetCC instructions - Here we just emit boilerplate code to set a byte-sized /// register, then move it to wherever the result should be. @@ -731,20 +811,6 @@ } -/// visitPHINode - Turn an LLVM PHI node into an X86 PHI node... -/// -void ISel::visitPHINode(PHINode &PN) { - MachineInstr *MI = BuildMI(BB, X86::PHI, PN.getNumOperands(), getReg(PN)); - - for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { - // FIXME: This will put constants after the PHI nodes in the block, which - // is invalid. They should be put inline into the PHI node eventually. - // - MI->addRegOperand(getReg(PN.getIncomingValue(i))); - MI->addPCDispOperand(PN.getIncomingBlock(i)); - } -} - /// visitCastInst - Here we have various kinds of copying with or without /// sign extension going on. void @@ -837,10 +903,13 @@ void ISel::visitGetElementPtrInst (GetElementPtrInst &I) { - emitGEPOperation(I.getOperand(0), I.op_begin()+1, I.op_end(), getReg(I)); + emitGEPOperation(BB, BB->end(), I.getOperand(0), + I.op_begin()+1, I.op_end(), getReg(I)); } -void ISel::emitGEPOperation(Value *Src, User::op_iterator IdxBegin, +void ISel::emitGEPOperation(MachineBasicBlock *BB, + MachineBasicBlock::iterator IP, + Value *Src, User::op_iterator IdxBegin, User::op_iterator IdxEnd, unsigned TargetReg) { const TargetData &TD = TM.getTargetData(); const Type *Ty = Src->getType(); @@ -887,9 +956,10 @@ Ty = SqTy->getElementType (); unsigned elementSize = TD.getTypeSize (Ty); unsigned elementSizeReg = makeAnotherReg(Type::UIntTy); - copyConstantToRegister (ConstantInt::get (typeOfSequentialTypeIndex, - elementSize), - elementSizeReg); + copyConstantToRegister(ConstantInt::get(typeOfSequentialTypeIndex, + elementSize), elementSizeReg, + BB, BB->end()); + unsigned idxReg = getReg (idx); // Emit a MUL to multiply the register holding the index by // elementSize, putting the result in memberOffsetReg. From lattner at cs.uiuc.edu Fri Dec 13 04:14:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 04:14:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-phi.ll Message-ID: <200212131013.EAA16830@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-phi.ll updated: 1.1 -> 1.2 --- Log message: Test more phi stuff --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-phi.ll diff -u llvm/test/Regression/Jello/test-phi.ll:1.1 llvm/test/Regression/Jello/test-phi.ll:1.2 --- llvm/test/Regression/Jello/test-phi.ll:1.1 Thu Nov 21 11:20:12 2002 +++ llvm/test/Regression/Jello/test-phi.ll Fri Dec 13 04:12:50 2002 @@ -1,4 +1,16 @@ ; test phi node + +%Y = global int 6 + +void %blah(int *%X) { + br label %T +T: + phi int* [%X, %0], [%Y, %Dead] + ret void +Dead: + br label %T +} + void %main() { br label %Test Test: From lattner at cs.uiuc.edu Fri Dec 13 04:14:03 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 04:14:03 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-phi.ll Message-ID: <200212131013.EAA17197@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-phi.ll updated: 1.2 -> 1.3 --- Log message: Return success on success --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-phi.ll diff -u llvm/test/Regression/Jello/test-phi.ll:1.2 llvm/test/Regression/Jello/test-phi.ll:1.3 --- llvm/test/Regression/Jello/test-phi.ll:1.2 Fri Dec 13 04:12:50 2002 +++ llvm/test/Regression/Jello/test-phi.ll Fri Dec 13 04:13:45 2002 @@ -11,11 +11,11 @@ br label %T } -void %main() { +int %main() { br label %Test Test: %X = phi int [7, %0], [%Y, %Dead] - ret void + ret int 0 Dead: %Y = shr int 12, ubyte 4 br label %Test From brukman at cs.uiuc.edu Fri Dec 13 04:43:00 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 04:43:00 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212131042.EAA17964@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.8 -> 1.9 --- Log message: Fixed bug with running out of registers. Also, reinstated namespace which disappeared during the last checkin. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.8 llvm/lib/CodeGen/RegAllocSimple.cpp:1.9 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.8 Fri Dec 13 03:54:36 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Fri Dec 13 04:42:31 2002 @@ -20,7 +20,7 @@ #include "Support/Statistic.h" #include -//namespace { +namespace { struct RegAllocSimple : public FunctionPass { TargetMachine &TM; MachineBasicBlock *CurrMBB; @@ -111,7 +111,7 @@ } }; -//} +} unsigned RegAllocSimple::allocateStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *regClass) @@ -289,6 +289,9 @@ // really delete the instruction delete MI; + + // make regs available to other instructions + clearAllRegs(); } //loop over each basic block From brukman at cs.uiuc.edu Fri Dec 13 04:44:00 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 04:44:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp Message-ID: <200212131043.EAA18021@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.11 -> 1.12 --- Log message: Treat longs as ints => pretend they're all 32-bit values and squeeze them into 32-bit registers. --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.11 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.12 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.11 Fri Dec 13 03:54:12 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Fri Dec 13 04:43:09 2002 @@ -55,6 +55,8 @@ case 1: opcode = X86::MOVmr8; break; case 2: opcode = X86::MOVmr16; break; case 4: opcode = X86::MOVmr32; break; + // FIXME: longs handled as ints + case 8: opcode = X86::MOVmr32; break; default: assert(0 && "Invalid data size!"); } @@ -74,6 +76,8 @@ case 1: opcode = X86::MOVrr8; break; case 2: opcode = X86::MOVrr16; break; case 4: opcode = X86::MOVrr32; break; + // FIXME: longs handled as ints + case 8: opcode = X86::MOVrr32; break; default: assert(0 && "Invalid data size!"); } @@ -92,6 +96,8 @@ case 1: opcode = X86::MOVir8; break; case 2: opcode = X86::MOVir16; break; case 4: opcode = X86::MOVir32; break; + // FIXME: longs handled as ints + case 8: opcode = X86::MOVir32; break; default: assert(0 && "Invalid data size!"); } From lattner at cs.uiuc.edu Fri Dec 13 04:51:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 04:51:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212131050.EAA18294@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.60 -> 1.61 --- Log message: Finish up iterator stuph --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.60 llvm/lib/Target/X86/InstSelectSimple.cpp:1.61 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.60 Fri Dec 13 04:09:43 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 04:50:40 2002 @@ -39,6 +39,17 @@ return MachineInstrBuilder(MI).addReg(DestReg, MOTy::Def); } +/// BMI - A special BuildMI variant that takes an iterator to insert the +/// instruction at as well as a basic block. +inline static MachineInstrBuilder BMI(MachineBasicBlock *BB, + MachineBasicBlock::iterator &I, + MachineOpCode Opcode, + unsigned NumOperands) { + MachineInstr *MI = new MachineInstr(Opcode, NumOperands, true, true); + I = ++BB->insert(I, MI); + return MachineInstrBuilder(MI); +} + namespace { struct ISel : public FunctionPass, InstVisitor { @@ -107,7 +118,9 @@ void visitAdd(BinaryOperator &B) { visitSimpleBinary(B, 0); } void visitSub(BinaryOperator &B) { visitSimpleBinary(B, 1); } void doMultiply(unsigned destReg, const Type *resultType, - unsigned op0Reg, unsigned op1Reg); + unsigned op0Reg, unsigned op1Reg, + MachineBasicBlock *MBB, + MachineBasicBlock::iterator &MBBI); void visitMul(BinaryOperator &B); void visitDiv(BinaryOperator &B) { visitDivRem(B); } @@ -152,7 +165,7 @@ // emitGEPOperation - Common code shared between visitGetElementPtrInst and // constant expression GEP support. // - void emitGEPOperation(MachineBasicBlock *BB, MachineBasicBlock::iterator IP, + void emitGEPOperation(MachineBasicBlock *BB, MachineBasicBlock::iterator&IP, Value *Src, User::op_iterator IdxBegin, User::op_iterator IdxEnd, unsigned TargetReg); @@ -161,7 +174,7 @@ /// void copyConstantToRegister(Constant *C, unsigned Reg, MachineBasicBlock *MBB, - MachineBasicBlock::iterator MBBI); + MachineBasicBlock::iterator &MBBI); /// makeAnotherReg - This method returns the next register number /// we haven't yet used. @@ -176,15 +189,13 @@ /// every time it is queried. /// unsigned getReg(Value &V) { return getReg(&V); } // Allow references - unsigned getReg(Value *V, MachineBasicBlock *BB = 0) { - MachineBasicBlock::iterator IPt; - if (BB == 0) { // Should we just append to the end of the current bb? - BB = this->BB; - IPt = BB->end(); - } else { // Otherwise, insert before the branch or ret instr... - IPt = BB->end()-1; - } - + unsigned getReg(Value *V) { + // Just append to the end of the current bb. + MachineBasicBlock::iterator It = BB->end(); + return getReg(V, BB, It); + } + unsigned getReg(Value *V, MachineBasicBlock *BB, + MachineBasicBlock::iterator &IPt) { unsigned &Reg = RegMap[V]; if (Reg == 0) { Reg = makeAnotherReg(V->getType()); @@ -265,7 +276,7 @@ /// void ISel::copyConstantToRegister(Constant *C, unsigned R, MachineBasicBlock *BB, - MachineBasicBlock::iterator IP) { + MachineBasicBlock::iterator &IP) { if (ConstantExpr *CE = dyn_cast(C)) { if (CE->getOpcode() == Instruction::GetElementPtr) { emitGEPOperation(BB, IP, CE->getOperand(0), @@ -292,11 +303,11 @@ ConstantUInt *CUI = cast(C); BMI(BB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue()); } - } else if (isa (C)) { + } else if (isa(C)) { // Copy zero (null pointer) to the register. BMI(BB, IP, X86::MOVir32, 1, R).addZImm(0); } else if (ConstantPointerRef *CPR = dyn_cast(C)) { - unsigned SrcReg = getReg(CPR->getValue()); + unsigned SrcReg = getReg(CPR->getValue(), BB, IP); BMI(BB, IP, X86::MOVrr32, 1, R).addReg(SrcReg); } else { std::cerr << "Offending constant: " << C << "\n"; @@ -328,7 +339,9 @@ // Get the incoming value into a virtual register. If it is not already // available in a virtual register, insert the computation code into // PredMBB - MI->addRegOperand(getReg(PN->getIncomingValue(i), PredMBB)); + MachineBasicBlock::iterator PI = PredMBB->end()-1; + MI->addRegOperand(getReg(PN->getIncomingValue(i), PredMBB, PI)); + // FIXME: Pass in the MachineBasicBlocks instead of the basic blocks... MI->addPCDispOperand(PN->getIncomingBlock(i)); // PredMBB @@ -636,7 +649,8 @@ /// The type of the result should be given as resultType. void ISel::doMultiply(unsigned destReg, const Type *resultType, - unsigned op0Reg, unsigned op1Reg) + unsigned op0Reg, unsigned op1Reg, + MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI) { unsigned Class = getClass (resultType); @@ -651,21 +665,23 @@ // Emit a MOV to put the first operand into the appropriately-sized // subreg of EAX. - BuildMI (BB, MovOpcode[Class], 1, Reg).addReg (op0Reg); + BMI(BB, MBBI, MovOpcode[Class], 1, Reg).addReg (op0Reg); // Emit the appropriate multiply instruction. - BuildMI (BB, MulOpcode[Class], 1).addReg (op1Reg); + BMI(BB, MBBI, MulOpcode[Class], 1).addReg (op1Reg); // Emit another MOV to put the result into the destination register. - BuildMI (BB, MovOpcode[Class], 1, destReg).addReg (Reg); + BMI(BB, MBBI, MovOpcode[Class], 1, destReg).addReg (Reg); } /// visitMul - Multiplies are not simple binary operators because they must deal /// with the EAX register explicitly. /// void ISel::visitMul(BinaryOperator &I) { + MachineBasicBlock::iterator MBBI = BB->end(); doMultiply (getReg (I), I.getType (), - getReg (I.getOperand (0)), getReg (I.getOperand (1))); + getReg (I.getOperand (0)), getReg (I.getOperand (1)), + BB, MBBI); } @@ -903,17 +919,18 @@ void ISel::visitGetElementPtrInst (GetElementPtrInst &I) { - emitGEPOperation(BB, BB->end(), I.getOperand(0), + MachineBasicBlock::iterator MI = BB->end(); + emitGEPOperation(BB, MI, I.getOperand(0), I.op_begin()+1, I.op_end(), getReg(I)); } void ISel::emitGEPOperation(MachineBasicBlock *BB, - MachineBasicBlock::iterator IP, + MachineBasicBlock::iterator &IP, Value *Src, User::op_iterator IdxBegin, User::op_iterator IdxEnd, unsigned TargetReg) { const TargetData &TD = TM.getTargetData(); const Type *Ty = Src->getType(); - unsigned basePtrReg = getReg(Src); + unsigned basePtrReg = getReg(Src, BB, IP); // GEPs have zero or more indices; we must perform a struct access // or array access for each one. @@ -936,8 +953,8 @@ unsigned memberOffset = TD.getStructLayout (StTy)->MemberOffsets[idxValue]; // Emit an ADD to add memberOffset to the basePtr. - BuildMI (BB, X86::ADDri32, 2, - nextBasePtrReg).addReg (basePtrReg).addZImm (memberOffset); + BMI(BB, IP, X86::ADDri32, 2, + nextBasePtrReg).addReg (basePtrReg).addZImm (memberOffset); // The next type is the member of the structure selected by the // index. Ty = StTy->getElementTypes ()[idxValue]; @@ -958,17 +975,17 @@ unsigned elementSizeReg = makeAnotherReg(Type::UIntTy); copyConstantToRegister(ConstantInt::get(typeOfSequentialTypeIndex, elementSize), elementSizeReg, - BB, BB->end()); + BB, IP); - unsigned idxReg = getReg (idx); + unsigned idxReg = getReg(idx, BB, IP); // Emit a MUL to multiply the register holding the index by // elementSize, putting the result in memberOffsetReg. unsigned memberOffsetReg = makeAnotherReg(Type::UIntTy); doMultiply (memberOffsetReg, typeOfSequentialTypeIndex, - elementSizeReg, idxReg); + elementSizeReg, idxReg, BB, IP); // Emit an ADD to add memberOffsetReg to the basePtr. - BuildMI (BB, X86::ADDrr32, 2, - nextBasePtrReg).addReg (basePtrReg).addReg (memberOffsetReg); + BMI(BB, IP, X86::ADDrr32, 2, + nextBasePtrReg).addReg (basePtrReg).addReg (memberOffsetReg); } // Now that we are here, further indices refer to subtypes of this // one, so we don't need to worry about basePtrReg itself, anymore. @@ -978,7 +995,7 @@ // basePtrReg. Move it to the register where we were expected to // put the answer. A 32-bit move should do it, because we are in // ILP32 land. - BuildMI (BB, X86::MOVrr32, 1, TargetReg).addReg (basePtrReg); + BMI(BB, IP, X86::MOVrr32, 1, TargetReg).addReg (basePtrReg); } From lattner at cs.uiuc.edu Fri Dec 13 05:01:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 05:01:01 2002 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/Shootout/lists.c Message-ID: <200212131100.FAA19003@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource/Shootout: lists.c updated: 1.3 -> 1.4 --- Log message: Remove references to stdout and stderr --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/Shootout/lists.c diff -u llvm/test/Programs/SingleSource/Shootout/lists.c:1.3 llvm/test/Programs/SingleSource/Shootout/lists.c:1.4 --- llvm/test/Programs/SingleSource/Shootout/lists.c:1.3 Fri Aug 9 15:06:18 2002 +++ llvm/test/Programs/SingleSource/Shootout/lists.c Fri Dec 13 05:00:38 2002 @@ -1,5 +1,5 @@ /* -*- mode: c -*- - * $Id: lists.c,v 1.3 2002/08/09 20:06:18 lattner Exp $ + * $Id: lists.c,v 1.4 2002/12/13 11:00:38 lattner Exp $ * http://www.bagley.org/~doug/shootout/ */ @@ -75,7 +75,7 @@ void list_print(char *msg, DLL *x) { DLL *xp, *first = x->next; int i = 0; - fputs(msg, stdout); + puts(msg); printf("length: %d\n", list_length(x)); for (xp=x->next; xp->next != first; xp=xp->next) { printf("i:%3d v:%3d n:%3d p:%3d\n", ++i, @@ -150,7 +150,7 @@ DLL *li3 = list_new(); /* compare li2 and li1 for equality*/ if (!list_equal(li2, li1)) { - fprintf(stderr, "li2 and li1 are not equal\n"); + printf("li2 and li1 are not equal\n"); exit(1); } while (!list_empty(li2)) { @@ -158,7 +158,7 @@ } /* li2 must now be empty*/ if (!list_empty(li2)) { - fprintf(stderr, "li2 should be empty now\n"); + printf("li2 should be empty now\n"); exit(1); } /* remove each individual item from right side of li3 and @@ -168,44 +168,44 @@ } /* li3 must now be empty */ if (!list_empty(li3)) { - fprintf(stderr, "li3 should be empty now\n"); + printf("li3 should be empty now\n"); exit(1); } /* reverse li1 in place */ list_reverse(li1); /* check that li1's first item is now SIZE */ if (list_first(li1)->val != SIZE) { - fprintf(stderr, "li1 first value wrong, wanted %d, got %d\n", + printf("li1 first value wrong, wanted %d, got %d\n", SIZE, list_first(li1)->val); exit(1); } /* check that li1's last item is now 1 */ if (list_last(li1)->val != 1) { - fprintf(stderr, "last value wrong, wanted %d, got %d\n", + printf("last value wrong, wanted %d, got %d\n", SIZE, list_last(li1)->val); exit(1); } /* check that li2's first item is now SIZE */ if (list_first(li2)->val != SIZE) { - fprintf(stderr, "li2 first value wrong, wanted %d, got %d\n", + printf("li2 first value wrong, wanted %d, got %d\n", SIZE, list_first(li2)->val); exit(1); } /* check that li2's last item is now 1 */ if (list_last(li2)->val != 1) { - fprintf(stderr, "last value wrong, wanted %d, got %d\n", + printf("last value wrong, wanted %d, got %d\n", SIZE, list_last(li2)->val); exit(1); } /* check that li1's length is still SIZE */ if (list_length(li1) != SIZE) { - fprintf(stderr, "li1 size wrong, wanted %d, got %d\n", + printf("li1 size wrong, wanted %d, got %d\n", SIZE, list_length(li1)); exit(1); } /* compare li1 and li2 for equality */ if (!list_equal(li1, li2)) { - fprintf(stderr, "li1 and li2 are not equal\n"); + printf("li1 and li2 are not equal\n"); exit(1); } len = list_length(li1); From lattner at cs.uiuc.edu Fri Dec 13 05:23:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 05:23:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212131122.FAA14744@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.61 -> 1.62 --- Log message: Rename all BMI MachineBasicBlock operands to MBB. Try to mess around with emitGEPOperation's elementSizeReg to make it work, again. --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.61 llvm/lib/Target/X86/InstSelectSimple.cpp:1.62 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.61 Fri Dec 13 04:50:40 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 05:22:48 2002 @@ -29,24 +29,25 @@ /// BMI - A special BuildMI variant that takes an iterator to insert the /// instruction at as well as a basic block. -inline static MachineInstrBuilder BMI(MachineBasicBlock *BB, +/// this is the version for when you have a destination register in mind. +inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB, MachineBasicBlock::iterator &I, MachineOpCode Opcode, unsigned NumOperands, unsigned DestReg) { MachineInstr *MI = new MachineInstr(Opcode, NumOperands+1, true, true); - I = ++BB->insert(I, MI); + I = ++MBB->insert(I, MI); return MachineInstrBuilder(MI).addReg(DestReg, MOTy::Def); } /// BMI - A special BuildMI variant that takes an iterator to insert the /// instruction at as well as a basic block. -inline static MachineInstrBuilder BMI(MachineBasicBlock *BB, +inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB, MachineBasicBlock::iterator &I, MachineOpCode Opcode, unsigned NumOperands) { MachineInstr *MI = new MachineInstr(Opcode, NumOperands, true, true); - I = ++BB->insert(I, MI); + I = ++MBB->insert(I, MI); return MachineInstrBuilder(MI); } @@ -194,7 +195,7 @@ MachineBasicBlock::iterator It = BB->end(); return getReg(V, BB, It); } - unsigned getReg(Value *V, MachineBasicBlock *BB, + unsigned getReg(Value *V, MachineBasicBlock *MBB, MachineBasicBlock::iterator &IPt) { unsigned &Reg = RegMap[V]; if (Reg == 0) { @@ -209,7 +210,7 @@ copyConstantToRegister(C, Reg, BB, IPt); } else if (GlobalValue *GV = dyn_cast(V)) { // Move the address of the global into the register - BMI(BB, IPt, X86::MOVir32, 1, Reg).addReg(GV); + BMI(MBB, IPt, X86::MOVir32, 1, Reg).addReg(GV); } else if (Argument *A = dyn_cast(V)) { // Find the position of the argument in the argument list. const Function *f = F->getFunction (); @@ -230,7 +231,7 @@ assert (argPos != -1 && "Argument not found in current function's argument list"); // Load it out of the stack frame at EBP + 4*argPos. - addRegOffset(BMI(BB, IPt, X86::MOVmr32, 4, Reg), X86::EBP, 4*argPos); + addRegOffset(BMI(MBB, IPt, X86::MOVmr32, 4, Reg), X86::EBP, 4*argPos); } return Reg; @@ -275,7 +276,7 @@ /// specified constant into the specified register. /// void ISel::copyConstantToRegister(Constant *C, unsigned R, - MachineBasicBlock *BB, + MachineBasicBlock *MBB, MachineBasicBlock::iterator &IP) { if (ConstantExpr *CE = dyn_cast(C)) { if (CE->getOpcode() == Instruction::GetElementPtr) { @@ -298,17 +299,17 @@ if (C->getType()->isSigned()) { ConstantSInt *CSI = cast(C); - BMI(BB, IP, IntegralOpcodeTab[Class], 1, R).addSImm(CSI->getValue()); + BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addSImm(CSI->getValue()); } else { ConstantUInt *CUI = cast(C); - BMI(BB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue()); + BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue()); } } else if (isa(C)) { // Copy zero (null pointer) to the register. - BMI(BB, IP, X86::MOVir32, 1, R).addZImm(0); + BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(0); } else if (ConstantPointerRef *CPR = dyn_cast(C)) { unsigned SrcReg = getReg(CPR->getValue(), BB, IP); - BMI(BB, IP, X86::MOVrr32, 1, R).addReg(SrcReg); + BMI(MBB, IP, X86::MOVrr32, 1, R).addReg(SrcReg); } else { std::cerr << "Offending constant: " << C << "\n"; assert(0 && "Type not handled yet!"); @@ -665,13 +666,13 @@ // Emit a MOV to put the first operand into the appropriately-sized // subreg of EAX. - BMI(BB, MBBI, MovOpcode[Class], 1, Reg).addReg (op0Reg); + BMI(MBB, MBBI, MovOpcode[Class], 1, Reg).addReg (op0Reg); // Emit the appropriate multiply instruction. - BMI(BB, MBBI, MulOpcode[Class], 1).addReg (op1Reg); + BMI(MBB, MBBI, MulOpcode[Class], 1).addReg (op1Reg); // Emit another MOV to put the result into the destination register. - BMI(BB, MBBI, MovOpcode[Class], 1, destReg).addReg (Reg); + BMI(MBB, MBBI, MovOpcode[Class], 1, destReg).addReg (Reg); } /// visitMul - Multiplies are not simple binary operators because they must deal @@ -924,7 +925,7 @@ I.op_begin()+1, I.op_end(), getReg(I)); } -void ISel::emitGEPOperation(MachineBasicBlock *BB, +void ISel::emitGEPOperation(MachineBasicBlock *MBB, MachineBasicBlock::iterator &IP, Value *Src, User::op_iterator IdxBegin, User::op_iterator IdxEnd, unsigned TargetReg) { @@ -953,7 +954,7 @@ unsigned memberOffset = TD.getStructLayout (StTy)->MemberOffsets[idxValue]; // Emit an ADD to add memberOffset to the basePtr. - BMI(BB, IP, X86::ADDri32, 2, + BMI(MBB, IP, X86::ADDri32, 2, nextBasePtrReg).addReg (basePtrReg).addZImm (memberOffset); // The next type is the member of the structure selected by the // index. @@ -972,8 +973,8 @@ // elements in the array.) Ty = SqTy->getElementType (); unsigned elementSize = TD.getTypeSize (Ty); - unsigned elementSizeReg = makeAnotherReg(Type::UIntTy); - copyConstantToRegister(ConstantInt::get(typeOfSequentialTypeIndex, + unsigned elementSizeReg = makeAnotherReg(typeOfSequentialTypeIndex); + copyConstantToRegister(ConstantSInt::get(typeOfSequentialTypeIndex, elementSize), elementSizeReg, BB, IP); @@ -984,7 +985,7 @@ doMultiply (memberOffsetReg, typeOfSequentialTypeIndex, elementSizeReg, idxReg, BB, IP); // Emit an ADD to add memberOffsetReg to the basePtr. - BMI(BB, IP, X86::ADDrr32, 2, + BMI(MBB, IP, X86::ADDrr32, 2, nextBasePtrReg).addReg (basePtrReg).addReg (memberOffsetReg); } // Now that we are here, further indices refer to subtypes of this @@ -995,7 +996,7 @@ // basePtrReg. Move it to the register where we were expected to // put the answer. A 32-bit move should do it, because we are in // ILP32 land. - BMI(BB, IP, X86::MOVrr32, 1, TargetReg).addReg (basePtrReg); + BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg (basePtrReg); } From lattner at cs.uiuc.edu Fri Dec 13 05:33:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 05:33:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212131132.FAA21760@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.62 -> 1.63 --- Log message: Implement cast bool to X --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.62 llvm/lib/Target/X86/InstSelectSimple.cpp:1.63 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.62 Fri Dec 13 05:22:48 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 05:31:59 2002 @@ -854,7 +854,7 @@ // 4) cast {int, uint, ptr} to {short, ushort} // cast {int, uint, ptr} to {sbyte, ubyte} // cast {short, ushort} to {sbyte, ubyte} - // + // 1) Implement casts to bool by using compare on the operand followed // by set if not zero on the result. if (targetType == Type::BoolTy) @@ -863,10 +863,11 @@ BuildMI (BB, X86::SETNEr, 1, destReg); return; } + // 2) Implement casts between values of the same type class (as determined // by getClass) by using a register-to-register move. - unsigned int srcClass = getClass (sourceType); - unsigned int targClass = getClass (targetType); + unsigned srcClass = sourceType == Type::BoolTy ? cByte : getClass(sourceType); + unsigned targClass = getClass (targetType); static const unsigned regRegMove[] = { X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 }; From brukman at cs.uiuc.edu Fri Dec 13 05:34:00 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 05:34:00 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212131133.FAA21776@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.9 -> 1.10 --- Log message: This should be more correct: invalidates physical registers that are used in an instruction to avoid using them to allocate to other virtual registers. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.9 llvm/lib/CodeGen/RegAllocSimple.cpp:1.10 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.9 Fri Dec 13 04:42:31 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Fri Dec 13 05:33:22 2002 @@ -79,6 +79,36 @@ RegClassIdx.clear(); } + /// Invalidates any references, real or implicit, to physical registers + /// + void invalidatePhysRegs(const MachineInstr *MI) { + unsigned Opcode = MI->getOpcode(); + const MachineInstrInfo &MII = TM.getInstrInfo(); + const MachineInstrDescriptor &Desc = MII.get(Opcode); + const unsigned *regs = Desc.ImplicitUses; + while (*regs) + RegsUsed[*regs++] = 1; + + regs = Desc.ImplicitDefs; + while (*regs) + RegsUsed[*regs++] = 1; + + + /* + for (int i = MI->getNumOperands() - 1; i >= 0; --i) { + const MachineOperand &op = MI->getOperand(i); + if (op.isMachineRegister()) + RegsUsed[op.getAllocatedRegNum()] = 1; + } + + for (int i = MI->getNumImplicitRefs() - 1; i >= 0; --i) { + const MachineOperand &op = MI->getImplicitOp(i); + if (op.isMachineRegister()) + RegsUsed[op.getAllocatedRegNum()] = 1; + } + */ + } + void cleanupAfterFunction() { RegMap.clear(); SSA2PhysRegMap.clear(); @@ -222,6 +252,12 @@ // get rid of the phi MBB->erase(MBB->begin()); + // a preliminary pass that will invalidate any registers that + // are used by the instruction (including implicit uses) + invalidatePhysRegs(MI); + + DEBUG(std::cerr << "num invalid regs: " << RegsUsed.size() << "\n"); + DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n"); MachineOperand &targetReg = MI->getOperand(0); @@ -285,13 +321,13 @@ saveVirtRegToStack(opBlock, opI, virtualReg, opPhysReg); } } + + // make regs available to other instructions + clearAllRegs(); } // really delete the instruction delete MI; - - // make regs available to other instructions - clearAllRegs(); } //loop over each basic block @@ -299,8 +335,9 @@ { MachineInstr *MI = *I; - // FIXME: add a preliminary pass that will invalidate any registers that + // a preliminary pass that will invalidate any registers that // are used by the instruction (including implicit uses) + invalidatePhysRegs(MI); // Loop over uses, move from memory into registers for (int i = MI->getNumOperands() - 1; i >= 0; --i) { From lattner at cs.uiuc.edu Fri Dec 13 05:40:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 05:40:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212131139.FAA14774@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.63 -> 1.64 --- Log message: lib/Target/X86/InstSelectSimple.cpp: The MachineBasicBlock variable name patrol hereby fines Chris Lattner one bag of nachos, for shadowing global names while his license to do so was under suspension. --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.63 llvm/lib/Target/X86/InstSelectSimple.cpp:1.64 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.63 Fri Dec 13 05:31:59 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 05:39:18 2002 @@ -207,7 +207,7 @@ // the register here... // if (Constant *C = dyn_cast(V)) { - copyConstantToRegister(C, Reg, BB, IPt); + copyConstantToRegister(C, Reg, MBB, IPt); } else if (GlobalValue *GV = dyn_cast(V)) { // Move the address of the global into the register BMI(MBB, IPt, X86::MOVir32, 1, Reg).addReg(GV); From lattner at cs.uiuc.edu Fri Dec 13 05:53:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 05:53:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212131152.FAA23180@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.64 -> 1.65 --- Log message: Insert phi code at top of block --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.64 llvm/lib/Target/X86/InstSelectSimple.cpp:1.65 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.64 Fri Dec 13 05:39:18 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 05:52:34 2002 @@ -340,9 +340,12 @@ // Get the incoming value into a virtual register. If it is not already // available in a virtual register, insert the computation code into // PredMBB - MachineBasicBlock::iterator PI = PredMBB->end()-1; + // + + MachineBasicBlock::iterator PI = PredMBB->begin(); + while ((*PI)->getOpcode() == X86::PHI) ++PI; + MI->addRegOperand(getReg(PN->getIncomingValue(i), PredMBB, PI)); - // FIXME: Pass in the MachineBasicBlocks instead of the basic blocks... MI->addPCDispOperand(PN->getIncomingBlock(i)); // PredMBB From brukman at cs.uiuc.edu Fri Dec 13 05:57:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 05:57:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212131156.FAA23677@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.10 -> 1.11 --- Log message: Need to insert all moves due to PHI nodes before *ALL* jumps in a predecessor basic block, as there could be multiple. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.10 llvm/lib/CodeGen/RegAllocSimple.cpp:1.11 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.10 Fri Dec 13 05:33:22 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Fri Dec 13 05:55:59 2002 @@ -92,21 +92,6 @@ regs = Desc.ImplicitDefs; while (*regs) RegsUsed[*regs++] = 1; - - - /* - for (int i = MI->getNumOperands() - 1; i >= 0; --i) { - const MachineOperand &op = MI->getOperand(i); - if (op.isMachineRegister()) - RegsUsed[op.getAllocatedRegNum()] = 1; - } - - for (int i = MI->getNumImplicitRefs() - 1; i >= 0; --i) { - const MachineOperand &op = MI->getImplicitOp(i); - if (op.isMachineRegister()) - RegsUsed[op.getAllocatedRegNum()] = 1; - } - */ } void cleanupAfterFunction() { @@ -297,6 +282,16 @@ MachineBasicBlock::iterator opI = opBlock->end(); MachineInstr *opMI = *(--opI); const MachineInstrInfo &MII = TM.getInstrInfo(); + // must backtrack over ALL the branches in the previous block, until no more + while ((MII.isBranch(opMI->getOpcode()) || MII.isReturn(opMI->getOpcode())) + && opI != opBlock->begin()) + { + opMI = *(--opI); + } + // move back to the first branch instruction so new instructions + // are inserted right in front of it and not in front of a non-branch + ++opI; + // insert the move just before the return/branch if (MII.isReturn(opMI->getOpcode()) || MII.isBranch(opMI->getOpcode())) From brukman at cs.uiuc.edu Fri Dec 13 06:01:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 06:01:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp Message-ID: <200212131200.GAA23798@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.12 -> 1.13 --- Log message: Cleaned up the code: factored out switch/case into a separate function, put constants in an array for quick lookup. Stole the idea from elsewhere in Jello. --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.12 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.13 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.12 Fri Dec 13 04:43:09 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Fri Dec 13 06:00:06 2002 @@ -23,6 +23,17 @@ : MRegisterInfo(X86Regs, sizeof(X86Regs)/sizeof(X86Regs[0])) { } +unsigned getIdx(unsigned dataSize) { + switch (dataSize) { + case 1: return 0; + case 2: return 1; + case 4: return 2; + // FIXME: longs handled as ints + case 8: return 2; + default: assert(0 && "Invalid data size!"); + } +} + MachineBasicBlock::iterator X86RegisterInfo::storeReg2RegOffset(MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI, @@ -30,15 +41,8 @@ unsigned ImmOffset, unsigned dataSize) const { - unsigned opcode; - switch (dataSize) { - case 1: opcode = X86::MOVrm8; break; - case 2: opcode = X86::MOVrm16; break; - case 4: opcode = X86::MOVrm32; break; - default: assert(0 && "Invalid data size!"); - } - - MachineInstr *MI = addRegOffset(BuildMI(opcode, 5), + static const unsigned Opcode[] = { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32 }; + MachineInstr *MI = addRegOffset(BuildMI(Opcode[getIdx(dataSize)], 5), DestReg, ImmOffset).addReg(SrcReg); return ++(MBB->insert(MBBI, MI)); } @@ -50,18 +54,9 @@ unsigned ImmOffset, unsigned dataSize) const { - unsigned opcode; - switch (dataSize) { - case 1: opcode = X86::MOVmr8; break; - case 2: opcode = X86::MOVmr16; break; - case 4: opcode = X86::MOVmr32; break; - // FIXME: longs handled as ints - case 8: opcode = X86::MOVmr32; break; - default: assert(0 && "Invalid data size!"); - } - - MachineInstr *MI = addRegOffset(BuildMI(opcode, 5).addReg(DestReg), - SrcReg, ImmOffset); + static const unsigned Opcode[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32 }; + MachineInstr *MI = addRegOffset(BuildMI(Opcode[getIdx(dataSize)], 5) + .addReg(DestReg), SrcReg, ImmOffset); return ++(MBB->insert(MBBI, MI)); } @@ -71,17 +66,9 @@ unsigned DestReg, unsigned SrcReg, unsigned dataSize) const { - unsigned opcode; - switch (dataSize) { - case 1: opcode = X86::MOVrr8; break; - case 2: opcode = X86::MOVrr16; break; - case 4: opcode = X86::MOVrr32; break; - // FIXME: longs handled as ints - case 8: opcode = X86::MOVrr32; break; - default: assert(0 && "Invalid data size!"); - } - - MachineInstr *MI = BuildMI(opcode, 2).addReg(DestReg).addReg(SrcReg); + static const unsigned Opcode[] = { X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 }; + MachineInstr *MI = + BuildMI(Opcode[getIdx(dataSize)], 2).addReg(DestReg).addReg(SrcReg); return ++(MBB->insert(MBBI, MI)); } @@ -91,17 +78,9 @@ unsigned DestReg, unsigned Imm, unsigned dataSize) const { - unsigned opcode; - switch (dataSize) { - case 1: opcode = X86::MOVir8; break; - case 2: opcode = X86::MOVir16; break; - case 4: opcode = X86::MOVir32; break; - // FIXME: longs handled as ints - case 8: opcode = X86::MOVir32; break; - default: assert(0 && "Invalid data size!"); - } - - MachineInstr *MI = BuildMI(opcode, 2).addReg(DestReg).addReg(Imm); + static const unsigned Opcode[] = { X86::MOVir8, X86::MOVir16, X86::MOVir32 }; + MachineInstr *MI = + BuildMI(Opcode[getIdx(dataSize)], 2).addReg(DestReg).addReg(Imm); return ++(MBB->insert(MBBI, MI)); } From lattner at cs.uiuc.edu Fri Dec 13 06:11:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 06:11:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-loop.ll Message-ID: <200212131210.GAA23848@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-loop.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: From brukman at cs.uiuc.edu Fri Dec 13 06:34:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 06:34:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212131233.GAA25081@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.11 -> 1.12 --- Log message: Fixed a bug where moves due to phis were being neglected. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.11 llvm/lib/CodeGen/RegAllocSimple.cpp:1.12 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.11 Fri Dec 13 05:55:59 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Fri Dec 13 06:33:31 2002 @@ -253,7 +253,7 @@ if (targetReg.isVirtualRegister()) { physReg = getFreeReg(virtualReg); } else { - physReg = targetReg.getAllocatedRegNum(); + physReg = virtualReg; } // Find the register class of the target register: should be the @@ -293,29 +293,25 @@ ++opI; - // insert the move just before the return/branch - if (MII.isReturn(opMI->getOpcode()) || MII.isBranch(opMI->getOpcode())) + // Retrieve the constant value from this op, move it to target + // register of the phi + if (opVal.getType() == MachineOperand::MO_SignExtendedImmed || + opVal.getType() == MachineOperand::MO_UnextendedImmed) { - // Retrieve the constant value from this op, move it to target - // register of the phi - if (opVal.getType() == MachineOperand::MO_SignExtendedImmed || - opVal.getType() == MachineOperand::MO_UnextendedImmed) - { - opI = RegInfo->moveImm2Reg(opBlock, opI, physReg, - (unsigned) opVal.getImmedValue(), - dataSize); - saveVirtRegToStack(opBlock, opI, virtualReg, physReg); - } else { - // Allocate a physical register and add a move in the BB - unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum(); - unsigned opPhysReg; // = getFreeReg(opVirtualReg); - opI = moveUseToReg(opBlock, opI, opVirtualReg, opPhysReg); - opI = RegInfo->moveReg2Reg(opBlock, opI, physReg, opPhysReg, - dataSize); - // Save that register value to the stack of the TARGET REG - saveVirtRegToStack(opBlock, opI, virtualReg, opPhysReg); - } - } + opI = RegInfo->moveImm2Reg(opBlock, opI, physReg, + (unsigned) opVal.getImmedValue(), + dataSize); + saveVirtRegToStack(opBlock, opI, virtualReg, physReg); + } else { + // Allocate a physical register and add a move in the BB + unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum(); + unsigned opPhysReg; // = getFreeReg(opVirtualReg); + opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg); + //opI = RegInfo->moveReg2Reg(opBlock, opI, physReg, opPhysReg, + // dataSize); + // Save that register value to the stack of the TARGET REG + saveVirtRegToStack(opBlock, opI, virtualReg, physReg); + } // make regs available to other instructions clearAllRegs(); From lattner at cs.uiuc.edu Fri Dec 13 07:05:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 07:05:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212131304.HAA25509@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.65 -> 1.66 --- Log message: Add sanity checks --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.65 llvm/lib/Target/X86/InstSelectSimple.cpp:1.66 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.65 Fri Dec 13 05:52:34 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 07:04:04 2002 @@ -35,6 +35,7 @@ MachineOpCode Opcode, unsigned NumOperands, unsigned DestReg) { + assert(I >= MBB->begin() && I <= MBB->end() && "Bad iterator!"); MachineInstr *MI = new MachineInstr(Opcode, NumOperands+1, true, true); I = ++MBB->insert(I, MI); return MachineInstrBuilder(MI).addReg(DestReg, MOTy::Def); @@ -46,6 +47,7 @@ MachineBasicBlock::iterator &I, MachineOpCode Opcode, unsigned NumOperands) { + assert(I > MBB->begin() && I <= MBB->end() && "Bad iterator!"); MachineInstr *MI = new MachineInstr(Opcode, NumOperands, true, true); I = ++MBB->insert(I, MI); return MachineInstrBuilder(MI); From lattner at cs.uiuc.edu Fri Dec 13 07:08:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 07:08:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212131307.HAA25597@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.66 -> 1.67 --- Log message: Fix bork in doMultiply --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.66 llvm/lib/Target/X86/InstSelectSimple.cpp:1.67 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.66 Fri Dec 13 07:04:04 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 07:07:42 2002 @@ -684,10 +684,11 @@ /// with the EAX register explicitly. /// void ISel::visitMul(BinaryOperator &I) { + unsigned DestReg = getReg(I); + unsigned Op0Reg = getReg(I.getOperand(0)); + unsigned Op1Reg = getReg(I.getOperand(1)); MachineBasicBlock::iterator MBBI = BB->end(); - doMultiply (getReg (I), I.getType (), - getReg (I.getOperand (0)), getReg (I.getOperand (1)), - BB, MBBI); + doMultiply(DestReg, I.getType(), Op0Reg, Op1Reg, BB, MBBI); } From brukman at cs.uiuc.edu Fri Dec 13 07:16:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 07:16:01 2002 Subject: [llvm-commits] CVS: llvm/tools/jello/Callback.cpp Emitter.cpp GlobalVars.cpp Message-ID: <200212131315.HAA26358@apoc.cs.uiuc.edu> Changes in directory llvm/tools/jello: Callback.cpp updated: 1.2 -> 1.3 Emitter.cpp updated: 1.4 -> 1.5 GlobalVars.cpp updated: 1.2 -> 1.3 --- Log message: Made status output debug-only (for testing diffs against lli). --- Diffs of the changes: Index: llvm/tools/jello/Callback.cpp diff -u llvm/tools/jello/Callback.cpp:1.2 llvm/tools/jello/Callback.cpp:1.3 --- llvm/tools/jello/Callback.cpp:1.2 Thu Dec 5 21:52:51 2002 +++ llvm/tools/jello/Callback.cpp Fri Dec 13 07:15:36 2002 @@ -6,6 +6,7 @@ //===----------------------------------------------------------------------===// #include "VM.h" +#include "Support/Statistic.h" #include #include #include @@ -26,10 +27,10 @@ unsigned RefAddr = *(unsigned*)ucp->uc_mcontext.gregs[REG_ESP]; RefAddr -= 4; // Backtrack to the reference itself... - std::cerr << "In SEGV handler! Addr=0x" << std::hex << RefAddr - << " ESP=0x" << ucp->uc_mcontext.gregs[REG_ESP] << std::dec - << ": Resolving call to function: " - << TheVM->getFunctionReferencedName((void*)RefAddr) << "\n"; + DEBUG(std::cerr << "In SEGV handler! Addr=0x" << std::hex << RefAddr + << " ESP=0x" << ucp->uc_mcontext.gregs[REG_ESP] << std::dec + << ": Resolving call to function: " + << TheVM->getFunctionReferencedName((void*)RefAddr) << "\n"); // Sanity check to make sure this really is a call instruction... assert(((unsigned char*)RefAddr)[-1] == 0xE8 && "Not a call instr!"); Index: llvm/tools/jello/Emitter.cpp diff -u llvm/tools/jello/Emitter.cpp:1.4 llvm/tools/jello/Emitter.cpp:1.5 --- llvm/tools/jello/Emitter.cpp:1.4 Thu Dec 12 23:40:28 2002 +++ llvm/tools/jello/Emitter.cpp Fri Dec 13 07:15:36 2002 @@ -9,6 +9,7 @@ #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Function.h" +#include "Support/Statistic.h" namespace { class Emitter : public MachineCodeEmitter { @@ -61,9 +62,9 @@ BBRefs.clear(); BBLocations.clear(); - std::cerr << "Finished Code Generation of Function: " - << F.getFunction()->getName() << ": " << CurByte-CurBlock - << " bytes of text\n"; + DEBUG(std::cerr << "Finished Code Generation of Function: " + << F.getFunction()->getName() << ": " << CurByte-CurBlock + << " bytes of text\n"); } void Emitter::startBasicBlock(MachineBasicBlock &BB) { Index: llvm/tools/jello/GlobalVars.cpp diff -u llvm/tools/jello/GlobalVars.cpp:1.2 llvm/tools/jello/GlobalVars.cpp:1.3 --- llvm/tools/jello/GlobalVars.cpp:1.2 Thu Dec 12 09:33:40 2002 +++ llvm/tools/jello/GlobalVars.cpp Fri Dec 13 07:15:36 2002 @@ -8,6 +8,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Constants.h" #include "llvm/Target/TargetMachine.h" +#include "Support/Statistic.h" #include "VM.h" #include @@ -28,9 +29,9 @@ // Allocate some memory for it! GlobalAddress[I] = new char[TD.getTypeSize(Ty)]; - std::cerr << "Allocated global '" << I->getName() - << "' to addr 0x" << std::hex << GlobalAddress[I] << std::dec - << "\n"; + DEBUG(std::cerr << "Allocated global '" << I->getName() + << "' to addr 0x" << std::hex << GlobalAddress[I] << std::dec + << "\n"); } else { assert(0 && "References to external globals not handled yet!"); } From brukman at cs.uiuc.edu Fri Dec 13 07:17:00 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Dec 13 07:17:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86TargetMachine.cpp Message-ID: <200212131316.HAA26375@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86TargetMachine.cpp updated: 1.4 -> 1.5 --- Log message: Make function code generation printing debug-only. --- Diffs of the changes: Index: llvm/lib/Target/X86/X86TargetMachine.cpp diff -u llvm/lib/Target/X86/X86TargetMachine.cpp:1.4 llvm/lib/Target/X86/X86TargetMachine.cpp:1.5 --- llvm/lib/Target/X86/X86TargetMachine.cpp:1.4 Fri Dec 13 00:46:30 2002 +++ llvm/lib/Target/X86/X86TargetMachine.cpp Fri Dec 13 07:16:14 2002 @@ -8,6 +8,7 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Target/TargetMachineImpls.h" #include "llvm/CodeGen/MachineFunction.h" +#include "Support/Statistic.h" #include "llvm/PassManager.h" #include "X86.h" #include @@ -39,7 +40,7 @@ // TODO: optional optimizations go here // Print the instruction selected machine code... - PM.add(createMachineFunctionPrinterPass()); + DEBUG(PM.add(createMachineFunctionPrinterPass())); // Perform register allocation to convert to a concrete x86 representation PM.add(createSimpleX86RegisterAllocator(*this)); @@ -48,9 +49,7 @@ // PM.add(createMachineFunctionPrinterPass()); // Print the register-allocated code - PM.add(createX86CodePrinterPass(*this, std::cerr)); - - //PM.add(createEmitX86CodeToMemory(*this)); + DEBUG(PM.add(createX86CodePrinterPass(*this, std::cerr))); return false; // success! } From lattner at cs.uiuc.edu Fri Dec 13 08:14:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 08:14:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp X86InstrInfo.def Message-ID: <200212131413.IAA27172@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.67 -> 1.68 X86InstrInfo.def updated: 1.40 -> 1.41 --- Log message: Implement indirect function calls --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.67 llvm/lib/Target/X86/InstSelectSimple.cpp:1.68 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.67 Fri Dec 13 07:07:42 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Dec 13 08:13:27 2002 @@ -577,8 +577,14 @@ break; } } - // Emit a CALL instruction with PC-relative displacement. - BuildMI (BB, X86::CALLpcrel32, 1).addPCDisp (CI.getCalledValue ()); + + if (Function *F = CI.getCalledFunction()) { + // Emit a CALL instruction with PC-relative displacement. + BuildMI(BB, X86::CALLpcrel32, 1).addPCDisp(F); + } else { + unsigned Reg = getReg(CI.getCalledValue()); + BuildMI(BB, X86::CALLr32, 1).addReg(Reg); + } // Adjust the stack by `bytesPushed' amount if non-zero if (bytesPushed > 0) Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.40 llvm/lib/Target/X86/X86InstrInfo.def:1.41 --- llvm/lib/Target/X86/X86InstrInfo.def:1.40 Thu Dec 12 23:04:37 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Fri Dec 13 08:13:27 2002 @@ -66,6 +66,10 @@ I(JE , "je", 0x84, M_BRANCH_FLAG, X86II::RawFrm | X86II::TB | X86II::Void, NoIR, NoIR) // je foo I(CALLpcrel32 , "call", 0xE8, M_BRANCH_FLAG, X86II::Void, NoIR, NoIR) // call pc+42 +I(CALLr32 , "call", 0xFF, M_BRANCH_FLAG, X86II::Void | X86II::MRMS2r | X86II::Arg32, + NoIR, NoIR) // call [r32] +I(CALLm32 , "call", 0xFF, M_BRANCH_FLAG, X86II::Void | X86II::MRMS2m | X86II::Arg32, + NoIR, NoIR) // call [m32] // Misc instructions I(LEAVE , "leave", 0xC9, 0, X86II::RawFrm, O_EBP, O_EBP) // leave From lattner at cs.uiuc.edu Fri Dec 13 08:16:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 08:16:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-call.ll Message-ID: <200212131415.IAA27462@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-call.ll updated: 1.3 -> 1.4 --- Log message: Test indirect call --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-call.ll diff -u llvm/test/Regression/Jello/test-call.ll:1.3 llvm/test/Regression/Jello/test-call.ll:1.4 --- llvm/test/Regression/Jello/test-call.ll:1.3 Thu Dec 12 22:43:32 2002 +++ llvm/test/Regression/Jello/test-call.ll Fri Dec 13 08:15:20 2002 @@ -1,7 +1,13 @@ declare void %exit(int) + +void %FP(void(int) * %F) { + call void %F(int 0) + ret void +} + int %main() { - call void %exit(int 0) + call void %FP(void(int)* %exit) ret int 1 } From lattner at cs.uiuc.edu Fri Dec 13 09:29:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 09:29:01 2002 Subject: [llvm-commits] CVS: llvm/tools/jello/Emitter.cpp Message-ID: <200212131528.JAA27630@apoc.cs.uiuc.edu> Changes in directory llvm/tools/jello: Emitter.cpp updated: 1.5 -> 1.6 --- Log message: Add statistic --- Diffs of the changes: Index: llvm/tools/jello/Emitter.cpp diff -u llvm/tools/jello/Emitter.cpp:1.5 llvm/tools/jello/Emitter.cpp:1.6 --- llvm/tools/jello/Emitter.cpp:1.5 Fri Dec 13 07:15:36 2002 +++ llvm/tools/jello/Emitter.cpp Fri Dec 13 09:28:42 2002 @@ -12,6 +12,8 @@ #include "Support/Statistic.h" namespace { + Statistic<> NumBytes("jello", "Number of bytes of machine code compiled"); + class Emitter : public MachineCodeEmitter { VM &TheVM; @@ -62,9 +64,11 @@ BBRefs.clear(); BBLocations.clear(); - DEBUG(std::cerr << "Finished Code Generation of Function: " - << F.getFunction()->getName() << ": " << CurByte-CurBlock - << " bytes of text\n"); + NumBytes += CurByte-CurBlock; + + DEBUG(std::cerr << "Finished CodeGen of [" << std::hex << (unsigned)CurBlock + << std::dec << "] Function: " << F.getFunction()->getName() + << ": " << CurByte-CurBlock << " bytes of text\n"); } void Emitter::startBasicBlock(MachineBasicBlock &BB) { From lattner at cs.uiuc.edu Fri Dec 13 10:50:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Dec 13 10:50:01 2002 Subject: [llvm-commits] CVS: llvm/tools/jello/VM.cpp VM.h jello.cpp Message-ID: <200212131649.KAA28184@apoc.cs.uiuc.edu> Changes in directory llvm/tools/jello: VM.cpp updated: 1.5 -> 1.6 VM.h updated: 1.4 -> 1.5 jello.cpp updated: 1.8 -> 1.9 --- Log message: Pass command line arguments to main --- Diffs of the changes: Index: llvm/tools/jello/VM.cpp diff -u llvm/tools/jello/VM.cpp:1.5 llvm/tools/jello/VM.cpp:1.6 --- llvm/tools/jello/VM.cpp:1.5 Thu Dec 12 23:40:28 2002 +++ llvm/tools/jello/VM.cpp Fri Dec 13 10:48:57 2002 @@ -38,9 +38,14 @@ } int VM::run(Function *F) { - int(*PF)() = (int(*)())getPointerToFunction(F); + int(*PF)(int, char**) = (int(*)(int, char**))getPointerToFunction(F); assert(PF != 0 && "Null pointer to function?"); - return PF(); + + unsigned NumArgs = 0; + for (; Argv[NumArgs]; ++NumArgs) + ; + + return PF(NumArgs, Argv); } void *VM::resolveFunctionReference(void *RefAddr) { Index: llvm/tools/jello/VM.h diff -u llvm/tools/jello/VM.h:1.4 llvm/tools/jello/VM.h:1.5 --- llvm/tools/jello/VM.h:1.4 Wed Dec 4 00:45:40 2002 +++ llvm/tools/jello/VM.h Fri Dec 13 10:48:57 2002 @@ -24,6 +24,7 @@ TargetMachine &TM; // The current target we are compiling to PassManager PM; // Passes to compile a function MachineCodeEmitter *MCE; // MCE object + char **Argv; // GlobalAddress - A mapping between LLVM values and their native code // generated versions... @@ -35,8 +36,8 @@ // std::map FunctionRefs; public: - VM(const std::string &name, Module &m, TargetMachine &tm) - : ExeName(name), M(m), TM(tm) { + VM(const std::string &name, char **AV, Module &m, TargetMachine &tm) + : ExeName(name), M(m), TM(tm), Argv(AV) { MCE = createEmitter(*this); // Initialize MCE setupPassManager(); registerCallback(); Index: llvm/tools/jello/jello.cpp diff -u llvm/tools/jello/jello.cpp:1.8 llvm/tools/jello/jello.cpp:1.9 --- llvm/tools/jello/jello.cpp:1.8 Tue Dec 3 16:48:59 2002 +++ llvm/tools/jello/jello.cpp Fri Dec 13 10:48:57 2002 @@ -16,6 +16,9 @@ cl::opt InputFile(cl::desc(""), cl::Positional, cl::init("-")); + cl::list + InputArgv(cl::ConsumeAfter, cl::desc("...")); + cl::opt MainFunction("f", cl::desc("Function to execute"), cl::init("main"), cl::value_desc("function name")); @@ -41,8 +44,18 @@ return 1; } + // Build an argv vector... + InputArgv.insert(InputArgv.begin(), InputFile); + char **Argv = new char*[InputArgv.size()+1]; + for (unsigned i = 0, e = InputArgv.size(); i != e; ++i) { + Argv[i] = new char[InputArgv[i].size()+1]; + std::copy(InputArgv[i].begin(), InputArgv[i].end(), Argv[i]); + Argv[i][InputArgv[i].size()] = 0; + } + Argv[InputArgv.size()] = 0; + // Create the virtual machine object... - VM TheVM(argv[0], *M.get(), *Target.get()); + VM TheVM(argv[0], Argv, *M.get(), *Target.get()); Function *F = M.get()->getNamedFunction(MainFunction); if (F == 0) { From lattner at cs.uiuc.edu Sat Dec 14 15:29:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Dec 14 15:29:01 2002 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200212142128.PAA01581@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.21 -> 1.22 --- Log message: Make stuff compiled with gccld not dump into the debugger if there's a problem --- Diffs of the changes: Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.21 llvm/tools/gccld/gccld.cpp:1.22 --- llvm/tools/gccld/gccld.cpp:1.21 Tue Jul 30 16:43:19 2002 +++ llvm/tools/gccld/gccld.cpp Sat Dec 14 15:28:32 2002 @@ -185,7 +185,7 @@ << "' for writing!\n"; return 1; } - Out2 << "#!/bin/sh\nlli -q $0.bc $*\n"; + Out2 << "#!/bin/sh\nlli -q -abort-on-exception $0.bc $*\n"; Out2.close(); // Make the script executable... From buschard at cs.uiuc.edu Sat Dec 14 19:33:00 2002 From: buschard at cs.uiuc.edu (Cameron Buschardt) Date: Sat Dec 14 19:33:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/construct.cpp emit.cpp regmask.h select.cpp sparc9.h sparcpriv.h test.cpp analyze.cpp analyze.h bitmath.h fvector.h salloc.cpp salloc.h sparcbin.cpp sparcbin.h sparcdis.cpp sparcdis.h main.cpp sparc9.hp Message-ID: <200212150132.TAA18216@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/BinInterface: construct.cpp added (r1.1) emit.cpp added (r1.1) regmask.h added (r1.1) select.cpp added (r1.1) sparc9.h updated: 1.6 -> 1.7 sparcpriv.h added (r1.1) test.cpp added (r1.1) analyze.cpp updated: 1.4 -> 1.5 analyze.h updated: 1.3 -> 1.4 bitmath.h updated: 1.3 -> 1.4 fvector.h updated: 1.3 -> 1.4 salloc.cpp updated: 1.1 -> 1.2 salloc.h updated: 1.1 -> 1.2 sparcbin.cpp updated: 1.1 -> 1.2 sparcbin.h updated: 1.1 -> 1.2 sparcdis.cpp updated: 1.4 -> 1.5 sparcdis.h updated: 1.3 -> 1.4 main.cpp (r1.1) removed sparc9.hp (r1.1) removed --- Log message: * Fixes made to disassembler to handle hybrid register-label * Stack allocation and spilling code completed * broke register allocation, construction, and emit code into seperate files * added better liveout handling code (now no problems are caused by claiming a value is liveout when it isn't) --- Diffs of the changes: Index: llvm/lib/Reoptimizer/BinInterface/sparc9.h diff -u /dev/null llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.7 --- /dev/null Sat Dec 14 19:32:43 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparc9.h Sat Dec 14 19:31:49 2002 @@ -0,0 +1,399 @@ +//***************************************************************************** +// +// Portable SPARC v9 Machine Code Definition Header +// +// +// 2002 Cameron Buschardt +//***************************************************************************** + +//********************************* +// Register Names +//********************************* +#define R_I7 31 +#define R_I6 30 +#define R_I5 29 +#define R_I4 28 +#define R_I3 27 +#define R_I2 26 +#define R_I1 25 +#define R_I0 24 + +#define R_L7 23 +#define R_L6 22 +#define R_L5 21 +#define R_L4 20 +#define R_L3 19 +#define R_L2 18 +#define R_L1 17 +#define R_L0 16 + +#define R_O7 15 +#define R_O6 14 +#define R_O5 13 +#define R_O4 12 +#define R_O3 11 +#define R_O2 10 +#define R_O1 9 +#define R_O0 8 + +#define R_G7 7 +#define R_G6 6 +#define R_G5 5 +#define R_G4 4 +#define R_G3 3 +#define R_G2 2 +#define R_G1 1 +#define R_G0 0 + +#define R_SP R_O6 +#define R_BP R_I6 // frame pointer + +extern char * reg_names[]; + +//********************************** +// Instruction bitfield definitions +//********************************** +#define INSTR_OP 31:30 +#define INSTR_A 29:29 +#define INSTR_FCN 29:25 +#define INSTR_DISP30 29:0 +#define INSTR_COND_H 28:25 +#define INSTR_RCOND_H 27:25 +#define INSTR_CC1_H 26:26 +#define INSTR_CC0_H 25:25 +#define INSTR_OP2 24:22 +#define INSTR_OP3 24:19 +#define INSTR_CC1_L 21:21 +#define INSTR_D16HI 21:20 +#define INSTR_D16LO 13:0 +#define INSTR_IMM22 21:0 +#define INSTR_DISP22 21:0 +#define INSTR_CC0_L 20:20 +#define INSTR_P 19:19 +#define INSTR_CC2 18:18 +#define INSTR_MOV_CC0 11:11 +#define INSTR_MOV_CC1 12:12 +#define INSTR_DISP19 18:0 +#define INSTR_IMPLDEP 18:0 +#define INSTR_COND_L 17:14 +#define INSTR_I 13:13 +#define INSTR_OPFCC 13:11 +#define INSTR_OPF 13:5 +#define INSTR_X 12:12 +#define INSTR_RCOND_L 12:10 +#define INSTR_IMMASI 12:5 +#define INSTR_SIMM13 12:0 +#define INSTR_OPFLOW_B 10:5 +#define INSTR_OPFLOW_S 9:5 +#define INSTR_SIMM11 10:0 +#define INSTR_SIMM10 9:0 +#define INSTR_CMASK 6:4 +#define INSTR_SWTRAP 6:0 +#define INSTR_SHCNT64 5:0 +#define INSTR_SHCNT32 4:0 +#define INSTR_MMASK 3:0 + +#define INSTR_RS1 18:14 +#define INSTR_RS2 4:0 +#define INSTR_RD 29:25 + + +#define RD_D16(i) ((RD_FLD(i, INSTR_D16HI) << 14) | RD_FLD(i, INSTR_D16LO)) + + +//********************************** +// Op-code classification +//********************************** +#define OP_CALL 0x00000001 /* 0b01 */ +#define OP_BRANCH 0x00000000 /* 0b00 */ +#define OP_2 0x00000002 /* 0b10 */ +#define OP_3 0x00000003 /* 0b11 */ + +//********************************** +// Branch Class Instructions +//********************************** +#define OP2_ILLTRAP 0x00000000 /* 0b000 */ //OP=OP_BRANCH +#define OP2_NOP 0x00000004 /* 0b100 */ //BRANCH +#define OP2_SETHI 0x00000004 /* 0b100 */ //BRANCH - uhh? duplicate? DOH =p +#define OP2_BICC 0x00000002 /* 0b010 */ +#define OP2_BPR 0x00000003 /* 0b011 */ +#define OP2_FB 0x00000006 /* 0b110 */ +#define OP2_FBP 0x00000005 /* 0b101 */ +#define OP2_BPICC 0x00000001 /* 0b001 */ + +//********************************** +// Register Condition Codes +//********************************** +#define RCOND_RZ 0x00000001 /* 0b001 */ +#define RCOND_RLEZ 0x00000002 /* 0b010 */ +#define RCOND_RNZ 0x00000005 /* 0b101 */ +#define RCOND_RGZ 0x00000006 /* 0b110 */ +#define RCOND_RGEZ 0x00000007 /* 0b111 */ + +//********************************** +// FPU Branch Conditions +//********************************** +#define COND_FBN 0x00000000 /* 0b0000 */ +#define COND_FBNE 0x00000001 /* 0b0001 */ +#define COND_FBLG 0x00000002 /* 0b0010 */ +#define COND_FBUL 0x00000003 /* 0b0011 */ +#define COND_FBL 0x00000004 /* 0b0100 */ +#define COND_FBUG 0x00000005 /* 0b0101 */ +#define COND_FBG 0x00000006 /* 0b0110 */ +#define COND_FBU 0x00000007 /* 0b0111 */ +#define COND_FBA 0x00000008 /* 0b1000 */ +#define COND_FBE 0x00000009 /* 0b1001 */ +#define COND_FBUE 0x0000000A /* 0b1010 */ +#define COND_FBGE 0x0000000B /* 0b1011 */ +#define COND_FBUGE 0x0000000C /* 0b1100 */ +#define COND_FBLE 0x0000000D /* 0b1101 */ +#define COND_FBULE 0x0000000E /* 0b1110 */ +#define COND_FBO 0x0000000F /* 0b1111 */ + +//********************************** +// Integer Branch Conditions +//********************************** +#define COND_BN 0x00000000 /* 0b0000 */ +#define COND_BE 0x00000001 /* 0b0001 */ +#define COND_BLE 0x00000002 /* 0b0010 */ +#define COND_BL 0x00000003 /* 0b0011 */ +#define COND_BLEU 0x00000004 /* 0b0100 */ +#define COND_BCS 0x00000005 /* 0b0101 */ +#define COND_BNEG 0x00000006 /* 0b0110 */ +#define COND_BVS 0x00000007 /* 0b0111 */ +#define COND_BA 0x00000008 /* 0b1000 */ +#define COND_BNE 0x00000009 /* 0b1001 */ +#define COND_BG 0x0000000A /* 0b1010 */ +#define COND_BGE 0x0000000B /* 0b1011 */ +#define COND_BGU 0x0000000C /* 0b1100 */ +#define COND_BCC 0x0000000D /* 0b1101 */ +#define COND_BPOS 0x0000000E /* 0b1110 */ +#define COND_BVC 0x0000000F /* 0b1111 */ + + +//********************************** +// Name Lookup tables +// index is Condition code +//********************************** + +extern char * fcond_names[]; +extern char * icond_names[]; +extern char * rcond_names[]; + +//********************************** +// Flag register encoding +//********************************** + +#define FLAG_FCC0 0x00000000 /* 0b000 */ +#define FLAG_FCC1 0x00000001 /* 0b001 */ +#define FLAG_FCC2 0x00000002 /* 0b010 */ +#define FLAG_FCC3 0x00000003 /* 0b011 */ +#define FLAG_ICC 0x00000004 /* 0b100 */ +#define FLAG_XCC 0x00000006 /* 0b110 */ + +extern char * cc_names[]; + + +//********************************** +// OP_2 class instructions +// +// present members: +// RD, OP3, RS1 +// if I=0 +// RS2 +// else +// SIMM13 +//********************************** + +#define OP3_ADD 0x00000000 /* 0b000000 */ +#define OP3_ADDC 0x00000008 /* 0b001000 */ +#define OP3_AND 0x00000001 /* 0b000001 */ +#define OP3_OR 0x00000002 /* 0b000010 */ +#define OP3_XOR 0x00000003 /* 0b000011 */ +#define OP3_SUB 0x00000004 /* 0b000100 */ +#define OP3_ANDN 0x00000005 /* 0b000101 */ +#define OP3_ORN 0x00000006 /* 0b000110 */ +#define OP3_XNOR 0x00000007 /* 0b000111 */ +#define OP3_SUBC 0x0000000C /* 0b001100 */ +#define OP3_ADDcc 0x00000010 /* 0b010000 */ +#define OP3_ADDCcc 0x00000018 /* 0b011000 */ +#define OP3_ANDcc 0x00000011 /* 0b010001 */ +#define OP3_ORcc 0x00000012 /* 0b010010 */ +#define OP3_XORcc 0x00000013 /* 0b010011 */ +#define OP3_SUBcc 0x00000014 /* 0b010100 */ +#define OP3_ANDNcc 0x00000015 /* 0b010101 */ +#define OP3_ORNcc 0x00000016 /* 0b010110 */ +#define OP3_XNORcc 0x00000017 /* 0b010111 */ +#define OP3_SUBCcc 0x0000001C /* 0b011100 */ +#define OP3_MULX 0x00000009 /* 0b001001 */ +#define OP3_SDIVX 0x0000002D /* 0b101101 */ +#define OP3_UDIVX 0x0000000D /* 0b001101 */ + +//Op3 members +#define OP3_CASA 0x0000003C /* 0b111100 */ +#define OP3_CASXA 0x0000003E /* 0b111110 */ + +//Instructions below generated with: +//OP=OP_2: RD, OP_3 RS1: {I=0 -> X & RS2 ,I=1 -> {X=0 -> SHCNT32 X=1->SHCNT64 }} +#define OP3_SLL 0x00000025 /* 0b100101 */ +#define OP3_SRL 0x00000026 /* 0b100110 */ +#define OP3_SRA 0x00000027 /* 0b100111 */ + +// class OP_3 +#define OP3_STFA 0x00000034 /* 0b110100 */ +#define OP3_STDFA 0x00000037 /* 0b110111 */ +#define OP3_STQFA 0x00000036 /* 0b110110 */ + +//Instructions below generated with: +//OP=OP_2: FCN +#define OP3_DONERETRY 0x0000003E /* 0b111110 */ +#define FCN_DONE 0 +#define FCN_RETRY 1 + +//These masks are valid for the instructions below +#define OPF_MASK_ONs 0x00000001 /* 0b0001 */ //these are valid for 'n' field +#define OPF_MASK_ONd 0x00000002 /* 0b0010 */ +#define OPF_MASK_ONq 0x00000003 /* 0b0011 */ +#define OPF_MASK_TOs 0x00000004 /* 0b0100 */ //these are valid for 't' field +#define OPF_MASK_TOd 0x00000008 /* 0b1000 */ +#define OPF_MASK_TOq 0x0000000C /* 0b1100 */ + +#define OPF_MASK_ON 0x00000003 /* 0b0011 */ +#define OPF_MASK_TO 0x0000000C /* 0b1100 */ + +//Instructions below generated with +//OP=OP_2: CC1_H, CC0_H, RS1, OPF, RS2 +#define OP3_FCMP 0x00000035 /* 0b110101 */ +#define OPF_FCMPn 0x00000050 /* 0b001010000 */ +#define OPF_FCMPEn 0x00000054 /* 0b001010100 */ + +//Instructions below generated with +//OP=OP_2: RD, OP3 RS1, OPF, RS2 +#define OP3_FPU 0x00000034 /* 0b110100 */ +#define OPF_FADDn 0x00000040 /* 0b001000000 */ +#define OPF_FSUBn 0x00000044 /* 0b001000100 */ +#define OPF_FMOVn 0x00000000 /* 0b000000000 */ +#define OPF_FNEGn 0x00000004 /* 0b000000100 */ +#define OPF_FABSn 0x00000008 /* 0b000001000 */ +#define OPF_FMULn 0x00000048 /* 0b001001000 */ +#define OPF_FDIVn 0x0000004C /* 0b001001100 */ +#define OPF_FSQRTn 0x00000028 /* 0b000101000 */ +#define OPF_FsTOx 0x00000081 /* 0b010000001 */ +#define OPF_FsTOi 0x000000D1 /* 0b011010001 */ +#define OPF_FsTOd 0x000000C9 /* 0b011001001 */ +#define OPF_FsTOq 0x000000CD /* 0b011001101 */ +#define OPF_FdTOx 0x00000082 /* 0b010000010 */ +#define OPF_FdTOi 0x000000D2 /* 0b011010010 */ +#define OPF_FdTOs 0x000000C6 /* 0b011000110 */ +#define OPF_FdTOq 0x000000CE /* 0b011001110 */ +#define OPF_FqTOx 0x00000083 /* 0b010000011 */ +#define OPF_FqTOi 0x000000D3 /* 0b011010011 */ +#define OPF_FqTOs 0x000000C7 /* 0b011000111 */ +#define OPF_FqTOd 0x000000CB /* 0b011001011 */ +#define OPF_FxTOt 0x00000080 /* 0b010000000 */ +#define OPF_FiTOt 0x000000C0 /* 0b011000000 */ +#define OPF_FsMULd 0x00000069 /* 0b001101001 */ +#define OPF_FdMULq 0x0000006E /* 0b001101110 */ + + +#define OP3_FLUSH 0x0000003B /* 0b111011 */ //OP=OP_2 RS1 {I=0 -> rs2, I=1->simm13} +#define OP3_FLUSHW 0x0000002B /* 0b101011 */ //OP=OP_2 I = 0 +#define OP3_JMPL 0x00000038 /* 0b111000 */ //OP=OP_2 RD, RS1 {I=0-> RS2, I=1->SIMM13} +#define OP3_LDFA 0x00000030 /* 0b110000 */ //OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13} +#define OP3_LDDFA 0x00000033 /* 0b110011 */ //OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13} +#define OP3_LDQFA 0x00000032 /* 0b110010 */ //OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13} + +#define OP3_LDSTUB 0x0000000D /* 0b001101 */ //OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13} +#define OP3_STB 0x00000005 /* 0b000101 */ +#define OP3_STH 0x00000006 /* 0b000110 */ +#define OP3_STW 0x00000004 /* 0b000100 */ +#define OP3_STX 0x00000007 /* 0b000111 */ +#define OP3_LDSB 0x00000009 /* 0b001001 */ +#define OP3_LDSH 0x0000000A /* 0b001010 */ +#define OP3_LDSW 0x00000008 /* 0b001000 */ +#define OP3_LDUB 0x00000001 /* 0b000001 */ +#define OP3_LDUH 0x00000002 /* 0b000010 */ +#define OP3_LDUW 0x00000000 /* 0b000000 */ +#define OP3_LDX 0x0000000B /* 0b001011 */ + + + +#define OP3_LDSTUBA 0x0000001D /* 0b011101 */ //OP=OP_3 RD, RS1 {I=0->RS2, IMM_ASI, I=1->SIMM13} + +#define OP3_MEMBAR 0x00000028 /* 0b101000 */ //OP=OP_2 CMASK, MMASK //WTF?!?! some bits get set + +//These two instructions are FUNKY as hell +#define OP3_FMOVcc 0x00000035 /* 0b110101 */ //OP=OP_2 RD, COND, OPF_CC, OPF_LOW, RS2 +#define OP3_MOVcc 0x0000002C /* 0b101100 */ // + + +#define OP3_POPC 0x0000002E /* 0b101110 */ +#define OP3_PREFETCH 0x0000002D /* 0b101101 */ +#define OP3_PREFETCHA 0x0000003D /* 0b111101 */ +#define OP3_RETURN 0x00000039 /* 0b111001 */ +#define OP3_SAVE 0x0000003C /* 0b111100 */ +#define OP3_RESTORE 0x0000003D /* 0b111101 */ + +#define OP3_SAVDRESTD 0x00000031 /* 0b110001 */ +#define FCN_SAVED 0 +#define FCN_RESTORED 1 + +#define OP3_TRAP 0x0000003A /* 0b111010 */ //integer trap + + +//***************************************************************************** +// Macros for generating useful instructions +//***************************************************************************** + +// Generic Load worm Reg+Offs +#define MK_LDX_ROFFS(dreg,regoffs ,stackoffs) \ + (MK_FLD(INSTR_OP, OP_3) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP3, OP3_LDX) | \ + MK_FLD(INSTR_RS1, regoffs) | \ + MK_FLD(INSTR_I , 1 ) | \ + MK_FLD(INSTR_SIMM13, stackoffs)) + + +// Load a word from O6/SP + stackoffs into dreg +#define MK_LDX_STACK(dreg, stackoffs) \ + (MK_FLD(INSTR_OP, OP_3) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP3, OP3_LDX) | \ + MK_FLD(INSTR_RS1, R_SP) | \ + MK_FLD(INSTR_I , 1 ) | \ + MK_FLD(INSTR_SIMM13, stackoffs)) + + +// Move a value between two registers +#define MK_MOV_R_R(dreg, sreg) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP3, OP3_MOVcc) | \ + MK_FLD(INSTR_RS2, sreg) | \ + MK_FLD(INSTR_I , 0 ) | \ + MK_FLD(INSTR_COND_L, COND_BA) | \ + MK_FLD(INSTR_CC2 , 1 ) | \ + MK_FLD(INSTR_MOV_CC1 , 1 ) | \ + MK_FLD(INSTR_MOV_CC0, 0 )) + +// Store a word in sreg to O6/SP + stackoffs +#define MK_STX_STACK(sreg, stackoffs) \ + (MK_FLD(INSTR_OP, OP_3) | \ + MK_FLD(INSTR_RD, sreg) | \ + MK_FLD(INSTR_OP3, OP3_STX) | \ + MK_FLD(INSTR_RS1, R_SP) | \ + MK_FLD(INSTR_I , 1 ) | \ + MK_FLD(INSTR_SIMM13, stackoffs)) + +// Add a constant to a register +#define MK_ADD_R_I(dreg, sreg, imm) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_RS1, sreg) | \ + MK_FLD(INSTR_SIMM13, imm) | \ + MK_FLD(INSTR_I, 1) | \ + MK_FLD(INSTR_OP3, OP3_ADD)) + + + Index: llvm/lib/Reoptimizer/BinInterface/analyze.cpp diff -u llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.4 llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.5 --- llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.4 Wed Nov 27 20:19:49 2002 +++ llvm/lib/Reoptimizer/BinInterface/analyze.cpp Sat Dec 14 19:30:54 2002 @@ -17,7 +17,7 @@ #include #include -#include "sparc9.hp" // SPARC 9 opcode and field definitions +#include "sparc9.h" // SPARC 9 opcode and field definitions #include "bitmath.h" #include "analyze.h" // API library #include @@ -138,6 +138,22 @@ return IF_RD | IF_RS1 | IF_RS2 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1 | IF_R_RS2; else return IF_RD | IF_RS1 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1; + + case OP3_MOVcc: + if (RD_FLD(instr, INSTR_I) == 0) + { + if (RD_FLD(instr, INSTR_COND_L)==COND_BA) + return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2; + else + return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2 | IF_RCC; + } + else + { + if (RD_FLD(instr, INSTR_COND_L)==COND_BA) + return IF_RD | IF_W_RD; + else + return IF_RD | IF_W_RD | IF_RCC; + } default: printf("Unknown:OP=0b10 OP3 = 0x%04X\n", RD_FLD(instr, INSTR_OP3)); @@ -225,14 +241,14 @@ // they are cancel read or write flags on that field if (flags & IF_RS1) - if (!RD_FLD(instr, INSTR_RS1)) + if ((1 << RD_FLD(instr, INSTR_RS1)) & RM_IGNORE) flags &= ~IF_R_RS1; if (flags & IF_RS2) - if (!RD_FLD(instr, INSTR_RS2)) + if ((1 << RD_FLD(instr, INSTR_RS2)) & RM_IGNORE) flags &= ~IF_R_RS2; if (flags & IF_RD) - if (!RD_FLD(instr, INSTR_RD)) + if ((1 << RD_FLD(instr, INSTR_RD)) & RM_IGNORE) flags &= ~(IF_R_RD | IF_W_RD); return flags; @@ -322,3 +338,4 @@ } } } + Index: llvm/lib/Reoptimizer/BinInterface/analyze.h diff -u llvm/lib/Reoptimizer/BinInterface/analyze.h:1.3 llvm/lib/Reoptimizer/BinInterface/analyze.h:1.4 --- llvm/lib/Reoptimizer/BinInterface/analyze.h:1.3 Wed Nov 27 20:19:50 2002 +++ llvm/lib/Reoptimizer/BinInterface/analyze.h Sat Dec 14 19:31:33 2002 @@ -13,6 +13,7 @@ #ifndef __ANALYZE__ #define __ANALYZE__ +#include "sparcpriv.h" #define IF_RS1 0x001 // Presence of RS1 field in instruction #define IF_RS2 0x002 // Presence of RS2 field in instruction @@ -29,6 +30,9 @@ // flags along side these when we store them in the // SSA form. This is the first 'user' flag available + + + /* Important NOTE! @@ -50,4 +54,5 @@ unsigned sparc_setbrdest(unsigned instr, signed reladdr); signed sparc_getbrdest(unsigned instr); -#endif \ No newline at end of file +#endif + Index: llvm/lib/Reoptimizer/BinInterface/bitmath.h diff -u llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.3 llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.4 --- llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.3 Wed Nov 27 20:19:51 2002 +++ llvm/lib/Reoptimizer/BinInterface/bitmath.h Sat Dec 14 19:31:33 2002 @@ -2,6 +2,16 @@ // // High Performance Bit Utility Functions // +// Contains +// * Routines for rounding to specific powers of 2 +// * Bitfield access macros +// * Sign extend macro +// * Extract bitmask of lowest bit set +// * Fast bit-set counting for sparse and dense bitfields +// * Fast modulo 3 test and remainder calculation +// * Fast parity calculation +// * Fast log2 (for 32-bit numbers ONLY!) +// // // 2002 Cameron Buschardt //***************************************************************************** @@ -10,26 +20,34 @@ #define __BITMATH_H__ //********************************* +// Misc functions +//********************************* +#define P2KM1(k) ((1 << (k))-1) // (2 ^ K) - 1 +#define ROUNDUP_P2(x, k) ((x+P2KM1(k)) &~ P2KM1(k)) +#define ROUNDUP32(x) ROUNDUP_P2(x,5) // round up to nearest mult of 32 + + +//********************************* // Bitfield manipulation Macros //********************************* #define FLD_UPPER(FLD_DEF) (1 ? FLD_DEF) #define FLD_LOWER(FLD_DEF) (0 ? FLD_DEF) -#define MASKBELOW(V) ((1 << V) - 1) -#define MASKEQBELOW(V) ((1 << V) | MASKBELOW(V)) //masks off everything ABOVE -#define RD_FLD(x, FLD) ((x & MASKEQBELOW(FLD_UPPER(FLD))) >> FLD_LOWER(FLD)) -#define MK_FLD(FLD, val) ((val << FLD_LOWER(FLD)) & MASKEQBELOW(FLD_UPPER(FLD))) -#define MASK_FLD(FLD) (MASKEQBELOW(FLD_UPPER(FLD)) & ~MASKBELOW(FLD_LOWER(FLD))) -#define RM_FLD(FLD, val) (val & ~(MASK_FLD(FLD))) +#define MASKBELOW(V) ((1 << V) - 1) +#define MASKEQBELOW(V) ((1 << V) | MASKBELOW(V)) //masks off everything ABOVE +#define RD_FLD(x, FLD) ((x & MASKEQBELOW(FLD_UPPER(FLD))) >> FLD_LOWER(FLD)) +#define MK_FLD(FLD, val) ((val << FLD_LOWER(FLD)) & MASKEQBELOW(FLD_UPPER(FLD))) +#define MASK_FLD(FLD) (MASKEQBELOW(FLD_UPPER(FLD)) & ~MASKBELOW(FLD_LOWER(FLD))) +#define RM_FLD(FLD, val) (val & ~(MASK_FLD(FLD))) //********************************** // Portable sign extend macros //********************************** -#define SIGN_EXTEND13(x) (x & 0x1000 ? -(-x & 0x1FFF): x) +#define SIGN_EXTEND13(x) (x & 0x1000 ? -(-x & 0x1FFF): x) #define SIGN_EXTEND(x, bits) (x & (1 << (bits-1)) ? -(-x & ((1 << bits)-1)):x) -#define IS_POWER_2(x) !(x & (x-1)) -#define LOWEST_BIT(x) x & ~(x & (x-1)) -#define UPPER_BITS(x) (x & (x-1)) +#define IS_POWER_2(x) !(x & (x-1)) +#define LOWEST_BIT(x) (x & ~(x & (x-1))) +#define UPPER_BITS(x) (x & (x-1)) // Good if expected number of bits set < 4 static int countbits_sparse(unsigned m) //VALIDATED @@ -85,7 +103,11 @@ return w & 1; } - +// +// Note: users of this function may depend on the fact +// that log2(0) will return 0. Since it is +// undefined I have chosen this value. +// static int log2(unsigned w) //VALIDATED { int n = 0; @@ -107,9 +129,10 @@ } w <<= 1; - return ((0xFFFFAA50 >> w) & 3)+n; + return ((0xFFFFAA50 >> w) & 3)+n; // this is a LUT } #endif + Index: llvm/lib/Reoptimizer/BinInterface/fvector.h diff -u llvm/lib/Reoptimizer/BinInterface/fvector.h:1.3 llvm/lib/Reoptimizer/BinInterface/fvector.h:1.4 --- llvm/lib/Reoptimizer/BinInterface/fvector.h:1.3 Wed Nov 27 20:19:51 2002 +++ llvm/lib/Reoptimizer/BinInterface/fvector.h Sat Dec 14 19:31:40 2002 @@ -21,8 +21,10 @@ T * v_begin; T * v_end; T * v_capacity; - StackAllocator * alloc; + Allocator * alloc; + // make sure we have MEMORY up to that element + // does not construct those positions void validate(T * pos) { assert(alloc); @@ -45,6 +47,23 @@ } fvector(const fvector &) {} + fvector & operator = (const fvector &) {} + void destroy(T * b, T * e) + { + while (b!=e) + { + b->~T(); + b++; + } + } + void construct(T * b, T * e) + { + while (b!=e) + { + new (b) T(); + b++; + } + } public: typedef T * iterator; @@ -52,14 +71,20 @@ iterator end() { return v_end; } void clear() { + assert(this); + destroy(v_begin, v_end); if (v_begin) alloc->free(v_begin); v_begin = v_capacity = v_end = NULL; } - unsigned size() { return v_end - v_begin; } + unsigned size() + { + assert(this); + return v_end - v_begin; + } - fvector(StackAllocator * a) + fvector(Allocator * a) { v_begin = v_end = v_capacity = NULL; alloc = a; @@ -72,7 +97,7 @@ } - void setallocator(StackAllocator * a) + void setallocator(Allocator * a) { assert(!alloc); alloc = a; @@ -82,29 +107,43 @@ { if (v_begin) return; - v_begin = (T*)alloc->alloc(sizeof(T) * v); + v_begin = (T*)alloc->alloc(sizeof(T) * v); v_end = v_begin; v_capacity = v_begin + v; } void push_back(const T & e) { - validate(v_end+1); - *v_end++ = e; + assert(this); + validate(v_end+1); + new (v_end) T(e); + v_end++; } void inc(unsigned amt) // increase size by this amt { validate(v_end + amt); + construct(v_end, v_end+amt); v_end += amt; } void resize(unsigned amt) { - validate(v_begin + amt); - v_end = v_begin + amt; + if ((v_begin+amt) < v_end) + { + // got shorter + destroy((v_begin+amt), v_end); + + } + else + { + // got longer + validate( v_begin+amt); + construct(v_end, v_begin+amt); + } + v_end = v_begin+amt; } - - T& operator[] (unsigned n) { return v_begin[n]; } + T& operator[] (unsigned n) { printf("write 0x%08X\n", v_begin+n); + return v_begin[n]; } const T & operator[] (unsigned n) const { return v_begin[n]; } @@ -112,3 +151,4 @@ #endif + Index: llvm/lib/Reoptimizer/BinInterface/salloc.cpp diff -u llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.2 --- llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.1 Wed Nov 27 20:19:55 2002 +++ llvm/lib/Reoptimizer/BinInterface/salloc.cpp Sat Dec 14 19:31:41 2002 @@ -6,17 +6,18 @@ // 2002 Cameron Buschardt //***************************************************************************** +#include #include "salloc.h" -#include +#include "bitmath.h" #include #include -#include "machine.h" +#include // work around incompetant compiler #define PRINTALLOC +// look up the size of a block by address #define BSIZE(x) *((unsigned *)((unsigned char *)x - sizeof (unsigned))) -extern "C" void memcpy(void *, void *, unsigned); void * StackAllocator::alloc(unsigned size) { @@ -45,7 +46,7 @@ unsigned oldsize=BSIZE(block); memcpy(r, block, oldsize); PRINTALLOC("Resize(%08X, %d) = new block: %08X \n", block, newsize, r); - + free(block); return r; } else @@ -84,20 +85,19 @@ StackAllocator::StackAllocator(unsigned size) { // round size up to next multiple of CACHE_LINE - size+= ((1 << MACHINE_CACHELINE)-1); - size&= ~((1 << MACHINE_CACHELINE)-1); - - begin = new unsigned char[size]; + size=ROUNDUP32(size); + begin = (unsigned char *)malloc(size); end = begin + size; top = begin; } StackAllocator::~StackAllocator() { - delete begin; + free(begin); } void StackAllocator::print() { printf("Stack alloc : %g kbytes used of %g kbytes\n", double(top-begin)/1000, double(end-begin)/1000); -} \ No newline at end of file +} + Index: llvm/lib/Reoptimizer/BinInterface/salloc.h diff -u llvm/lib/Reoptimizer/BinInterface/salloc.h:1.1 llvm/lib/Reoptimizer/BinInterface/salloc.h:1.2 --- llvm/lib/Reoptimizer/BinInterface/salloc.h:1.1 Wed Nov 27 20:19:55 2002 +++ llvm/lib/Reoptimizer/BinInterface/salloc.h Sat Dec 14 19:31:41 2002 @@ -3,11 +3,15 @@ // // Definitions of Base Allocator class and Stack allocator // +// +// // 2002 Cameron Buschardt //***************************************************************************** #ifndef __SALLOC_H__ #define __SALLOC_H__ +#include +#include //********************************* // Generic Allocator @@ -22,6 +26,8 @@ virtual void*resize(void * block , unsigned newsize) = 0; }; + + //********************************* // Stack Allocator //********************************* @@ -43,4 +49,5 @@ }; -#endif \ No newline at end of file +#endif + Index: llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.2 --- llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.1 Wed Nov 27 20:20:11 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp Sat Dec 14 19:32:10 2002 @@ -23,10 +23,10 @@ #include "fvector.h" // fast vector (sits on stack allocator) #include "analyze.h" // SPARC analysis library (gets flag masks for instrs) #include "sparcbin.h" // Prototype for this class -#include "machine.h" // machine constants for cache optimizations +#include "sparcpriv.h" // Private definitions#include "machine.h" // machine constants for cache optimizations #include "sparcdis.h" // prototype for sparc disassembler #include "bitmath.h" // header of optimized binary math routines -#include "sparc9.hp" // SPARC 9 opcode definitions +#include "sparc9.h" // SPARC 9 opcode definitions #include using std::pair; @@ -38,17 +38,6 @@ #include -#define IF_ALUOP (IF_USR << 1) -#define IF_PHI (IF_USR << 2) -#define IF_NODELIVEIN (IF_USR << 3) // instr field is register to bind to -#define IF_NODELIVEOUT (IF_USR << 4) // instr field is register dest.. genrs1 is source value -#define IF_LIVEOUT (IF_USR << 5) // is a normal instr liveout -#define IF_BRINTERNAL (IF_USR << 6) // is this an INTERNAL branch if so use ibranch - - -// a call instruction will spill all the outgoing registers O0->O7 (R8-R15) -#define R_CALLSPILLS 0x0000FF00 -#define R_ALLOCREGS 0xFFFFBFFE // allocate all regs except R0(G0), O6(R14)(SP) // @@ -65,27 +54,6 @@ -// -// Register state definition used during selection process -// - -// -// The usecount and current register any value is in. -// Note! reg can either be a stack location (negative) or -// a register index (positive) -// If reg < 0 then then stackidx = ~reg -// - -struct SSATerm -{ - unsigned uses; - unsigned lastuse; //end of live range - int reg; //negative denotes stack location - - - SSATerm() : uses(0), reg(0) {} -}; - @@ -97,483 +65,30 @@ // -struct vreginfo -{ - unsigned uses; - unsigned lastuse; - int mreg; -}; -// Register field. VERY similar to a bitvector -// with a few minor changes - -struct regmask -{ - fvector freemap; - - - // Construct freemap, initially mark everyone free - regmask(StackAllocator * a, unsigned maxregs) - : freemap(a) - { - // make sure unsigned it at least 32-bits - assert(countbits_dense(~unsigned(0))>=32); - - // calculate size of freemap - freemap.inc( (maxregs + 31) >> 5 ); //round up to nearest 32 - for (int k = 0; k < freemap.size(); k++) - freemap[k] = ~0; - } - - // returns 0 on failure - unsigned allocreg() // allocate ANY register - { - for (int k = 0; k> 5] |= 1 << (idx & 31); // mark it free - } - - void grabreg(unsigned idx) - { - freemap[idx >> 5] &= ~(1 << (idx & 31)); // grab it - } - - void set32(unsigned mask) - { - freemap[0] = mask; - } - - // count how many are free in the lowest 32. - unsigned count32() - { - return countbits_dense(freemap[0]); - } - - unsigned isreg32() - { - return freemap[0]; - } -}; unsigned BinInterface::emit(unsigned char * out) { + int spillreg; + int memspills[32]; + unsigned touched, stack; // Table to look up virtual register for SSA node // this is done to condense PHI node references - fvector ssa_to_vreg(&alloca); - fvector vregs(&alloca); // index 0 never assigned + regalloc regs(alloca); + - select(ssa_to_vreg, vregs); // condense phi nodes and calculate + select(regs); // condense phi nodes and calculate // live ranges - return emit_gen(out, ssa_to_vreg, vregs); // do linear scan register allocation + return emit_gen(out, regs); // do linear scan register allocation // interleaved with code generation } -int BinInterface::spillreg(int spillloc, unsigned * & out, fvector & vregs, regmask & freeregs, unsigned hwregs[32]) -{ - - // Select a live range to spill - unsigned min_cnt = 0xFFFFFFFF; - unsigned min_idx = 0; - - for (int j = 0; j < 32; j++) - { - if (!hwregs[j]) - continue; - - vreginfo & v = vregs[hwregs[j]]; - if (v.uses < min_cnt) - { - min_cnt = v.uses; - min_idx = j; - } - } - // Spill the live range to the location we allocated - vregs[hwregs[min_idx]].mreg = spillloc; // update map - - // spill the live-range - *out++=(MK_STX_STACK(min_idx, 8*(spillloc - 32))); - - return min_idx; -} - -// -// Spill load -// - loads value into register (performing spill if needed) -// - validates use constraints and identifies the end of a live-range -// -int BinInterface::spill_load(int useid, int id, unsigned * & out, fvector & vregs, regmask & freeregs, unsigned hwregs[32]) -{ - int rs1 = vregs[id].mreg; - - if (rs1 >= 32) // not a hardware register? - { - // First try allocating a candindate register - int sreg = freeregs.allocreg(); - - // if sreg wasn't a hardware register spill something into it - // and return the register we spilled - if (sreg >= 32) - sreg = spillreg(sreg, out, vregs, freeregs, hwregs); - - // update the virtual register map - hwregs[sreg] = id; - vregs[id].mreg = sreg; - freeregs.freereg(rs1); // free the old area since we're loading it - - // perform a spill load on the parameters - *out++=(MK_LDX_STACK(sreg, 8*(rs1-32))); - - - return sreg; - } - else - return rs1; //it was already in a register -} - -unsigned BinInterface::emit_gen(unsigned char * cde, fvector &ssa_to_vreg, fvector & vregs) -{ - unsigned * out = (unsigned *) cde; - - fvector > fwdbranch(&alloca); // pairs of instruction addrs +destination section #'s - fvector secaddr(&alloca); // address of section - - secaddr.inc(sections.size()); - - // register allocation state - regmask freeregs(&alloca,itable.size()); // includes stack positions - unsigned hwregs[32]; // vreg index in that register - freeregs.set32(R_ALLOCREGS); // mark candidate registers free - - for (int s = 0; s< 32; s++) - hwregs[s] = 0; - - // Allocate registers that are marked as live in values - for (int p = 0; plivein.reg; - vregs[ ssa_to_vreg[livein[p]] ].mreg = mreg; - - // Mark that register not free - freeregs.grabreg(mreg); - hwregs[mreg] = ssa_to_vreg[livein[p]]; - } - - // Iterate across instructions - for (int s=0;sflags; - - if (flags & IF_NODELIVEOUT) - { - // load the value into a register. - int gen = ssa_to_vreg[instr->liveout.gen]; - int sreg = vregs[gen].mreg; - int dreg = instr->liveout.reg; - - assert(dreg < 32); - - if (sreg==dreg) //we don't need to do a transfer - continue; - - // spill whatever is in DREG - if (hwregs[dreg]) - { - int spillloc = freeregs.allocreg(); - // Spill the live range to the location we allocated - if (spillloc < 32) - { - hwregs[spillloc] = hwregs[dreg]; - *out++=(MK_MOV_R_R(spillloc, dreg)); - } - else - { - *out++=(MK_STX_STACK(dreg, 8*(spillloc - 32))); - } - vregs[hwregs[dreg]].mreg = spillloc; // update map - - } - - // use dreg - if (sreg >= 32) // stack variable? - { - *out++=(MK_LDX_STACK(dreg, 8*(sreg - 32))); - } - else - { - *out++=(MK_MOV_R_R(dreg,sreg)); - } - - // we don't want to accidentally spill this register. - // make sure it is allocated and mark it no use - - hwregs[dreg] = 0; // off-limits - freeregs.grabreg(dreg); - continue; - } - - // make sure this is ACTUALLY an instruction and not a phi node - if (! (flags & (IF_ALUOP | IF_BR))) - continue; - - unsigned spilled = 0; // a mask of the registers - // that were spilled for the parameters - // this is here so that when we spill - // a live range that is in a reigster - - // we don't accidentally spill one of the OTHER - // parameters - - // load parameters of instruction - if (flags & IF_R_RS1) - { - int id = ssa_to_vreg[instr->alu.genrs1]; - // verify value is in register / return register - rs1 = spill_load(i,id, out, vregs, freeregs, hwregs); - - } - - if (flags & IF_R_RS2) - { - int id = ssa_to_vreg[instr->alu.genrs2]; - rs2 = spill_load(i,id, out, vregs, freeregs, hwregs); - } - - if (flags & IF_R_RD) - { - int id = ssa_to_vreg[instr->alu.genrd]; - rd = spill_load(i,id, out, vregs, freeregs, hwregs); - } - - - // - // Branch instructions must have their target fixed up - // (note that the next instruction emitted is guaranteed - // to be the actual instruction and not a spill fixup) - if (flags & IF_BR) - { - if (flags & IF_BRINTERNAL) - { - // we need to fix up destination. If this is a backward branch no problem - // forward branches we store a backtable FIXME - if (instr->ibranch.dest <= s) - { - unsigned rel = secaddr[instr->ibranch.dest] - out; - instr->instr = sparc_setbrdest(instr->instr,rel); - } - else - fwdbranch.push_back(pair(out, instr->ibranch.dest)); - } - else - { - // do absolute jump - unsigned rel = instr->ebranch.dest - out; - instr->instr = sparc_setbrdest(instr->instr,rel); - } - } - - - // parameters of instruction have been loaded. Figure out what register we're going to write - // destination to - unsigned ins = instr->instr; - // mask off and replace rs1 - if (flags & IF_R_RS1) - { - ins = RM_FLD(INSTR_RS1, ins) | MK_FLD(INSTR_RS1, rs1); - int vid = ssa_to_vreg[instr->alu.genrs1]; - if (vregs[vid].lastuse == i) - { - freeregs.freereg(vregs[vid].mreg); - hwregs[rs1] = 0; - } - } - - if (flags & IF_R_RS2) - { - ins = RM_FLD(INSTR_RS2, ins) | MK_FLD(INSTR_RS2, rs2); - int vid = ssa_to_vreg[instr->alu.genrs2]; - - if (vregs[vid].lastuse == i) - { - freeregs.freereg(vregs[vid].mreg); - hwregs[rs2] = 0; - } - } - - if (flags & IF_R_RD) - { - ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, rd); - int vid = ssa_to_vreg[instr->alu.genrd]; - if (vregs[vid].lastuse == i) - { - freeregs.freereg(vregs[vid].mreg); - hwregs[rd] = 0; - } - } - - if (flags & IF_W_RD) - { - int id = ssa_to_vreg[i]; - - // We need to generate and store a result. We should check to see - // if any registers are currently 'free'. If not we must spill one. - - int dreg = freeregs.allocreg(); - - if (dreg >= 32) // got a stack location? spill something to it - dreg = spillreg(dreg, out, vregs, freeregs, hwregs); - - hwregs[dreg] = i; - - // emit the instruction using this register as the destination - ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, dreg); - *out++=(ins); - - // modify the map to reflect this register as containing this SSA value - vregs[id].mreg = dreg; - - } - else - *out++=(ins); // no dreg? just emit it - } - } - - // - // Handle forward branches. - // - for(int t = 0; t & i = fwdbranch[t]; - - unsigned rel = secaddr[i.second] - out; - *i.first = sparc_setbrdest(*i.first,rel); - } - - return out- ((unsigned *)cde); -} -void BinInterface::select(fvector &ssa_to_vreg,fvector &vregs) -{ - int free_vreg = 1 ; // first free - - // Mark everyone as having no register assigned - ssa_to_vreg.inc(itable.size()); - for (int k = 0; kflags; - - if (flags & IF_PHI) - { - for (int p=0; p< instr->phi.params->size(); p++) - { - int id = (*instr->phi.params)[p]; - ssa_to_vreg[id] = free_vreg; - } - ssa_to_vreg[i] = free_vreg; - free_vreg++; - } - } - - // size the vreg structures and initialize - vregs.inc(itable.size()); - for (int p = 0 ; p < free_vreg; p++) - vregs[p].uses = vregs[p].lastuse = vregs[p].mreg = 0; - - - // Assign Vregs to non-phi parameters. Calculate usage information - // for ALL virtual registers. - for (int s=0;sflags; - - if (!ssa_to_vreg[i]) //not got a vreg yet? - { - // allocate one - ssa_to_vreg[i] = free_vreg; - vregs.inc(1); - vregs[free_vreg].uses = vregs[free_vreg].lastuse = vregs[free_vreg].mreg = 0; - free_vreg++; - } - - if (flags & IF_NODELIVEOUT) - { - vregs[ ssa_to_vreg[instr->liveout.gen] ].uses++; - vregs[ ssa_to_vreg[instr->liveout.gen] ].lastuse = i; - continue; - } - - // note since PHI nodes have been collapsed - // through the vreg assignment. we don't need to process them! =p - // Livein nodes are also skipped - if (flags & (IF_ALUOP | IF_BR)) - { - if (flags & IF_R_RS1) // do we read from RS1? - { - int id = ssa_to_vreg[instr->alu.genrs1]; - vregs[id].uses++; - vregs[id].lastuse = i; - } - if (flags & IF_R_RS2) // do we read from RS2? - { - int id = ssa_to_vreg[instr->alu.genrs2]; - vregs[id].uses++; - vregs[id].lastuse = i; - } - if (flags & IF_R_RD) // do we read from RD? - { - int id = ssa_to_vreg[instr->alu.genrd]; - vregs[id].uses++; - vregs[id].lastuse = i; - } - } - } -} - - @@ -585,222 +100,20 @@ instruction * BinInterface::allocphi() { - instruction * phi = (instruction *)alloca.alloc(sizeof(instruction)); + instruction * phi = (instruction *)alloca->alloc(sizeof(instruction)); phi->flags = IF_PHI; phi->next = phi->prev = phi->self = itable.size(); itable.push_back(phi); // allocate memory for fvector AND call constructor - phi->phi.params = (fvector *)alloca.alloc(sizeof(fvector)); - new ((void *)phi->phi.params) fvector(&alloca); + phi->phi.params = (fvector *)alloca->alloc(sizeof(fvector)); + new ((void *)phi->phi.params) fvector(alloca); return phi; } -void BinInterface::process_markgen(unsigned s, unsigned map[32],fvector & regmaps) -{ - // iterate all instructions in this section - for (int i = begin(s); i!=end(s); ) - { - // look at instruction - instruction * instr = itable[i]; - unsigned flags = instr->flags; - - // what uses? - if (flags & IF_R_RS1) - { - int rs1 = RD_FLD(instr->instr, INSTR_RS1); - if (!map[rs1]) - // oops. we just made a reference to an incoming value. Instantiate - map[rs1] = allocnodelivein(sections[0],rs1); - - instr->alu.genrs1 = map[rs1]; - } - - if (flags & IF_R_RS2) - { - int rs2 = RD_FLD(instr->instr, INSTR_RS2); - if (!map[rs2]) - map[rs2] = allocnodelivein(sections[0],rs2); - instr->alu.genrs2 = map[rs2]; - } - - if (flags & IF_R_RD) - { - int rd = RD_FLD(instr->instr, INSTR_RD); - if (!map[rd]) - map[rd] = allocnodelivein(sections[0], rd); - instr->alu.genrd = map[rd]; - } - - // does he write to a register? - if (flags & IF_W_RD) - map[RD_FLD(instr->instr, INSTR_RD)] = i; - else if (flags & IF_PHI) - map[instr->instr] = instr->self; // use phi node for reg val - - // advance - i = instr->next; - - } -} - - -void BinInterface::process_section(unsigned s, unsigned map[32],fvector & regmaps) -{ - // We inherit map from parent (p->t->e) -- FIX HANDLING OF MULTIPLE EPILOGS - for (int v=0;v<32;v++) - regmaps[s][v] = map[v]; - - // iterate all instructions in this section - for (int i = begin(s); i!=end(s); ) - { - // look at instruction - instruction * instr = itable[i]; - unsigned flags = instr->flags; - - // is the instruction a branch? - if (flags & IF_BRINTERNAL) - { - - // follow the branch and MERGE the tables. - int brdest = instr->ibranch.dest; - - for (int q=0;q<32;q++) - if (!regmaps[brdest][q]) - regmaps[brdest][q] = map[q]; - else if (regmaps[brdest][q]!=map[q]) - { - // we need a phi node - or we need to append to one - instruction * d = itable[regmaps[brdest][q]]; - if (d->flags & IF_PHI) - { - if (!map[q]) - map[q] = allocnodelivein(s,q); //must have been livein - d->phi.params->push_back(map[q]); // append to a phi node - } - else - { - // create a phi node - instruction * phi = allocphi(); - - // Live in check - if (!regmaps[brdest][q]) - regmaps[brdest][q] = allocnodelivein(s,q); - - phi->phi.params->push_back(regmaps[brdest][q]); - - // live in check - if (!map[q]) - map[q] = allocnodelivein(s,q); - - phi->phi.params->push_back(map[q]); - - // link in the phi node and update both maps - insert_instr(sections[s], phi); - map[q] = phi->self; - regmaps[brdest][q] = phi->self; - phi->instr = q; // the register it applies to - } - } - - } - - // does he write to a register? - if (flags & IF_W_RD) - map[RD_FLD(instr->instr, INSTR_RD)] = i; - - i = instr->next; - } -} - - -void BinInterface::reduce() -{ - fvector regmaps(&alloca); - - regmaps.resize(sections.size()); - - - unsigned map[32],mapepi[32]; // current map - - - for (int i = 0; i < 32; i++) - map[i] = 0; // instruction ID #0 is a loop header. - // there is no way a register could - // be generated by it. So we use 0 - // as a NULL marker - - // Clear header maps - for (int s=0;sinstr holds the register number in question - // - // Execute program in order and connect phi nodes - // - - // clear the map - for (int v=0;v<32;v++) - map[v] = 0; - - process_markgen(SECTION_PROLOG, map, regmaps); - process_markgen(SECTION_TRACE , map, regmaps); - - - for (int s=SECTION_TRACE+1;sflags & IF_PHI) - { - // if any of the PHI parameters are marked live out, - // the phi node itself becomes liveout. - unsigned flags; - for (int s = 0; s< instr->phi.params->size(); s++) - flags |= itable[(*instr->phi.params)[s]]->flags; - if (flags & IF_LIVEOUT) - { - allocnodeliveout(s,i, mapepi[i]); - } - } - if (itable[mapepi[i]]->flags & IF_LIVEOUT) - { - // this one is liveout. Let's do the insertion - allocnodeliveout(s,i, mapepi[i]); - - } - } - } -} - void BinInterface::process_branch(const insertion & i, unsigned ** brdest, int scns) { unsigned cid = i.idstart; @@ -822,7 +135,7 @@ unsigned * dest = ibegin + fwd; // create a branch instruction - instr = (instruction *)alloca.alloc(sizeof(instruction)); + instr = (instruction *)alloca->alloc(sizeof(instruction)); instr->flags = flags; // scan for branch destination @@ -845,7 +158,7 @@ else { // create a generic ALU instruction - instr = (instruction *)alloca.alloc(sizeof(instruction)); + instr = (instruction *)alloca->alloc(sizeof(instruction)); instr->flags = flags | IF_ALUOP; instr->alu.genccf = instr->alu.genrs1 = instr->alu.genrs2 = 0; // zero reg } @@ -868,19 +181,20 @@ void BinInterface::complete() { + int p; assert(sections.size() <= MAX_SECTIONS); // Compute branch destination table by section unsigned * brdest[MAX_SECTIONS]; - for (int p = 0; pself,instr->livein.reg); } - else if (instr->flags & IF_NODELIVEOUT) + else if (instr->flags & IF_REGSHUFFLE) { - printf("r%02d: liveout[l%04d]\n", instr->liveout.reg, instr->liveout.gen); + for (int k = 0; kregshuffle.shuffles->size(); k++) + printf("r%02d: liveout[l%04d]\n", (*instr->regshuffle.shuffles)[k].reg, (*instr->regshuffle.shuffles)[k].gen); } else if (instr->flags & IF_PHI) { @@ -944,7 +259,7 @@ void BinInterface::print() { - alloca.print(); + //alloca->print(); for (int p = 0; p< sections.size(); p++) { @@ -984,24 +299,25 @@ // AFTER INSTR AFTER->NEXT void BinInterface::push_section() { - // create header node - instruction * instr = (instruction *)alloca.alloc(sizeof(instruction)); + // create header node + instruction * instr = (instruction *)alloca->alloc(sizeof(instruction)); instr->next = itable.size(); instr->prev = itable.size(); instr->flags = 0; instr->self = itable.size(); - sections.push_back(itable.size()); itable.push_back(instr); - } BinInterface::BinInterface(unsigned instr_count) - : alloca(BIN_INIT_HEAP_SIZE + instr_count * 16) , itable(&alloca), sections(&alloca), - queue(&alloca), livein(&alloca) { + alloca = new StackAllocator(BIN_INIT_HEAP_SIZE + instr_count*16); + itable.setallocator(alloca); + sections.setallocator(alloca); + queue.setallocator(alloca); + livein.setallocator(alloca); // create prolog and trace link nodes push_section(); push_section(); @@ -1010,7 +326,7 @@ unsigned BinInterface::allocnodelivein(int s, int reg) { int idx = itable.size(); - instruction * instr = (instruction *)alloca.alloc(sizeof(instruction)); + instruction * instr = (instruction *)alloca->alloc(sizeof(instruction)); instr->flags = IF_NODELIVEIN; instr->livein.reg = reg; instr->self = idx; @@ -1021,13 +337,12 @@ } -unsigned BinInterface::allocnodeliveout(int s, int reg, unsigned source) +unsigned BinInterface::allocnodeshuffles(int s, fvector * shuffles) { int idx = itable.size(); - instruction * instr = (instruction *)alloca.alloc(sizeof(instruction)); - instr->flags = IF_NODELIVEOUT; - instr->liveout.reg = reg; - instr->liveout.gen = source; + instruction * instr = (instruction *)alloca->alloc(sizeof(instruction)); + instr->flags = IF_REGSHUFFLE; + instr->regshuffle.shuffles = shuffles; instr->self = idx; itable.push_back(instr); @@ -1054,10 +369,12 @@ itable.clear(); sections.clear(); queue.clear(); - - alloca.clear(); + livein.clear(); + alloca->clear(); // create prolog and trace link nodes push_section(); push_section(); } + + Index: llvm/lib/Reoptimizer/BinInterface/sparcbin.h diff -u llvm/lib/Reoptimizer/BinInterface/sparcbin.h:1.1 llvm/lib/Reoptimizer/BinInterface/sparcbin.h:1.2 --- llvm/lib/Reoptimizer/BinInterface/sparcbin.h:1.1 Wed Nov 27 20:20:33 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcbin.h Sat Dec 14 19:32:13 2002 @@ -13,67 +13,25 @@ #include "salloc.h" #include "fvector.h" #include "analyze.h" - -// Since instructions are dynmically sized union structures -// *AND* all member types are native integers, I am storing -// them as arrays of undefined length. Here is a list of -// valid indices for the various types of instructions. -// -// - -// flags -struct instruction -{ - unsigned next; - unsigned prev; - unsigned self; - unsigned flags; - - unsigned instr; - union - { - struct - { - unsigned genrs1; - unsigned genrs2; - unsigned genccf; - unsigned genrd; //ingenious SUN.. we can read from RD!?! - } alu; - struct - { - unsigned dest; // id # of destination section - } ibranch; // internal branch - struct - { - unsigned * dest; - } ebranch; // external branch - struct - { - fvector * params; - }phi; - struct - { - unsigned reg; - } livein; - struct - { - unsigned reg; - unsigned gen; - } liveout; - }; -}; +#include "sparcpriv.h" struct vreginfo; struct regmask; +struct regmask32; +struct instruction; +struct regalloc; +struct shufflepair; +static const unsigned SECTION_PROLOG =0; +static const unsigned SECTION_TRACE =1; class BinInterface { private: - StackAllocator alloca; // primary stack allocator + Allocator *alloca; // primary stack allocator fvector itable; // maps an unsigned ID - // to an instruction + // to an instruction fvector sections; fvector livein; // pointers to all livein nodes @@ -104,15 +62,15 @@ // returns itable index for new live in node unsigned allocnodelivein(int s, int reg); - unsigned allocnodeliveout(int s,int reg, unsigned gen); - - void select(fvector &ssa_to_vreg,fvector &vregs); + unsigned allocnodeshuffles(int s, fvector * shuffles); + int spill_load(int vreg, regmask32 & rmask,const int memspills[32], int & freereg, int spills[3], int & spill_cnt, unsigned * & out); + void select(regalloc & regs); - int spillreg(int spillloc, unsigned * & out, fvector & vregs, regmask & freeregs, unsigned hwregs[32]); + int spillreg(int spillloc, unsigned * & out, fvector & vregs, regmask & freeregs, unsigned hwregs[32]); - int spill_load(int useid,int id, unsigned * & out, fvector & vregs, regmask & freeregs, unsigned hwregs[32]); - unsigned emit_gen(unsigned char * out, fvector &ssa_to_vreg, fvector & vregs); + void prepare_exit(const regalloc & regalloc, fvector * mod, unsigned * & out); + unsigned emit_gen(unsigned char * out, const regalloc & regs); public: @@ -121,8 +79,6 @@ // Call newepilog() to get the ID of a new epilog section unsigned newepilog(); // IDs of prolog and trace sections - const static unsigned SECTION_PROLOG =0; - const static unsigned SECTION_TRACE =1; // initial instruction block insertion. specify section number // and iterator to machine instructions @@ -208,4 +164,6 @@ BinInterface(unsigned instr_count); }; -#endif \ No newline at end of file +#endif + + Index: llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.4 llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.5 --- llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.4 Wed Nov 27 20:20:37 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp Sat Dec 14 19:32:14 2002 @@ -22,52 +22,60 @@ #include #include -#include "sparc9.hp" // SPARC 9 definitions +#include "sparc9.h" // SPARC 9 definitions #include "bitmath.h" #include +void sparc_printop_rs1(unsigned instr, int labelrs1) +{ + if (labelrs1) + printf("l%d", labelrs1); + else + printf("%s", reg_names[RD_FLD(instr, INSTR_RS1)]); +} + +void sparc_printop_rs2(unsigned instr, int labelrs2) +{ + if (labelrs2) + printf("l%d", labelrs2); + else + printf("%s", reg_names[RD_FLD(instr, INSTR_RS2)]); +} + +void sparc_printop_rrd(unsigned instr, int labelrrd) +{ + if (labelrrd) + printf("l%d", labelrrd); + else + printf("%s", reg_names[RD_FLD(instr, INSTR_RD)]); +} + void sparc_printbr(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) { // look at the OP2 field if (RD_FLD(instr,INSTR_OP2)==OP2_ILLTRAP) - printf("ILLTRAP .. "); + printf("ILLTRAP"); else if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI) { if (RD_FLD(instr, INSTR_RD) == 0) printf("NOP"); else { - if (!labels) - printf("SETHI %%hi(%08X), r%d", RD_FLD(instr, INSTR_IMM22) << 10, RD_FLD(instr, INSTR_RD)); - else - printf("SETHI %%hi(%08X), l%d", RD_FLD(instr, INSTR_IMM22) << 10, labelrd); + printf("SETHI %%hi(%08X), ", RD_FLD(instr, INSTR_IMM22) << 10); + sparc_printop_rrd(instr, labelrd); } } else if (RD_FLD(instr, INSTR_OP2)==OP2_BICC) { - printf("%s disp:%08X",icond_names[RD_FLD(instr, INSTR_COND_H)], SIGN_EXTEND(RD_FLD(instr,INSTR_DISP22),22)); + printf("b%s disp:%08X",icond_names[RD_FLD(instr, INSTR_COND_H)], SIGN_EXTEND(RD_FLD(instr,INSTR_DISP22),22)); } else if (RD_FLD(instr, INSTR_OP2)==OP2_BPR) { //A, RCOND_H, D16HI, P, RS1, D16LO - if (!labels) - { - printf("P%s%s%s r%d, %06X " , rcond_names[RD_FLD(instr, INSTR_RCOND_H)], - RD_FLD(instr, INSTR_A) ? ",a" : "", - RD_FLD(instr, INSTR_P) ? ",pt" : ",pn", - RD_FLD(instr, INSTR_RS1), - RD_D16(instr) - ); - } - else - { - printf("P%s%s%s l%d, %06X " , rcond_names[RD_FLD(instr, INSTR_RCOND_H)], - RD_FLD(instr, INSTR_A) ? ",a" : "", - RD_FLD(instr, INSTR_P) ? ",pt" : ",pn", - labelrs1, - RD_D16(instr) - ); - } + printf("P%s%s%s ", rcond_names[RD_FLD(instr, INSTR_RCOND_H)], + RD_FLD(instr, INSTR_A) ? ",a" : "", + RD_FLD(instr, INSTR_P) ? ",pt" : ",pn"); + sparc_printop_rs1(instr, labelrs1); } else if (RD_FLD(instr, INSTR_OP2)==OP2_FB) { @@ -87,18 +95,21 @@ // OP=OP_2 : RD, OP3, RS1: {I=0 -> RS2 I=1->SIMM13} if (RD_FLD(instr, INSTR_I)==0) { + printf("%s ", basename); if (!labels) - printf("%s r%d <- r%d ,r%d",basename, RD_FLD(instr, INSTR_RD),RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_RS2)); - else - printf("%s l%d <- l%d ,l%d",basename, labelrd,labelrs1, labelrs2); + printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); + sparc_printop_rs1(instr, labelrs1); + printf(" ,"); + sparc_printop_rs2(instr, labelrs2); } else { + printf("%s ", basename); if (!labels) - printf("%s r%d <- r%d ,%d",basename, RD_FLD(instr, INSTR_RD),RD_FLD(instr, INSTR_RS1), SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - else - printf("%s l%d <- l%d ,%d",basename, labelrd,labelrs1, SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - } + printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); + sparc_printop_rs1(instr, labelrs1); + printf(" , %d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + } } void sparc_printshf(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) @@ -106,17 +117,22 @@ //OP=OP_2: RD, OP_3 RS1: {I=0 -> X & RS2 ,I=1 -> {X=0 -> SHCNT32 X=1->SHCNT64 }} if (RD_FLD(instr, INSTR_I)==0) { + printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64)); if (!labels) - printf("%s%d r%d <- r%d, by r%d ",(RD_FLD(instr, INSTR_X)==0 ? 32 : 64), basename, RD_FLD(instr, INSTR_RD), RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_RS2)); - else - printf("%s%d l%d <- l%d, by l%d ",(RD_FLD(instr, INSTR_X)==0 ? 32 : 64), basename, labelrd, labelrs1, labelrs2); + printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); + + sparc_printop_rs1(instr, labelrs1); + printf(", "); + sparc_printop_rs2(instr, labelrs2); } else { + printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64)); if (!labels) - printf("%s%d r%d <- r%d, by 0x%04X ", basename,(RD_FLD(instr, INSTR_X)==0 ? 32 : 64), RD_FLD(instr, INSTR_RD), RD_FLD(instr, INSTR_RS1), (RD_FLD(instr, INSTR_X)==0 ? RD_FLD(instr, INSTR_SHCNT32) : RD_FLD(instr, INSTR_SHCNT64)) ); - else - printf("%s%d l%d <- l%d, by 0x%04X ", basename,(RD_FLD(instr, INSTR_X)==0 ? 32 : 64), labelrd, labelrs1, (RD_FLD(instr, INSTR_X)==0 ? RD_FLD(instr, INSTR_SHCNT32) : RD_FLD(instr, INSTR_SHCNT64)) ); + printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); + + sparc_printop_rs1(instr, labelrs1); + printf(", 0x%04X", (RD_FLD(instr, INSTR_X)==0 ? RD_FLD(instr, INSTR_SHCNT32) : RD_FLD(instr, INSTR_SHCNT64))); } } @@ -217,16 +233,18 @@ case OP3_MOVcc: { - if (RD_FLD(instr, INSTR_I)==0) - printf("mov%s(%s) r%d <- r%d", icond_names[RD_FLD(instr, INSTR_COND_L)], - cc_names[(RD_FLD(instr, INSTR_CC2) << 2) | (RD_FLD(instr, INSTR_MOV_CC1) << 1) | RD_FLD(instr, INSTR_MOV_CC0)], - RD_FLD(instr, INSTR_RD), - RD_FLD(instr, INSTR_RS2)); + printf("mov%s(%s) ", icond_names[RD_FLD(instr, INSTR_COND_L)], + cc_names[(RD_FLD(instr, INSTR_CC2) << 2) | (RD_FLD(instr, INSTR_MOV_CC1) << 1) | RD_FLD(instr, INSTR_MOV_CC0)]); + + if (!labels) + printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); + + if (RD_FLD(instr, INSTR_I)==0) // RS2 + sparc_printop_rs2(instr, labelrs2); else - printf("mov%s(%s) r%d <- %d", icond_names[RD_FLD(instr, INSTR_COND_L)], - cc_names[(RD_FLD(instr, INSTR_CC2) << 2) | (RD_FLD(instr, INSTR_MOV_CC1) << 1) | RD_FLD(instr, INSTR_MOV_CC0)], - RD_FLD(instr, INSTR_RD), - SIGN_EXTEND(RD_FLD(instr, INSTR_SIMM11),11)); + printf("%d", SIGN_EXTEND(RD_FLD(instr, INSTR_SIMM11), 11)); + + return; } @@ -365,17 +383,20 @@ case OP3_JMPL: //OP=OP_2 RD, RS1 {I=0-> RS2, I=1->SIMM13} if (RD_FLD(instr, INSTR_I)==0) { - if (!labels) - printf("JMPL link:r%d, to: r%d+r%d", RD_FLD(instr, INSTR_RD),RD_FLD(instr, INSTR_RS1),RD_FLD(instr, INSTR_RS2) ); - else - printf("JMPL link:l%d, to: l%d+l%d", labelrd,labelrs1,labelrs2 ); + printf("jmpl link:"); + sparc_printop_rrd(instr, labelrd); + printf(", to: "); + sparc_printop_rs1(instr, labelrs1); + printf("+"); + sparc_printop_rs2(instr, labelrs2); } else { - if (!labels) - printf("JMPL link:r%d, to: r%d+%d", RD_FLD(instr, INSTR_RD),RD_FLD(instr, INSTR_RS1),SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)) ); - else - printf("JMPL link:l%d, to: l%d+%d", labelrd,labelrs1,SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)) ); + printf("jmpl link:"); + sparc_printop_rrd(instr, labelrd); + printf(", to: "); + sparc_printop_rs1(instr, labelrs1); + printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); } return; @@ -386,52 +407,54 @@ case OP3_RETURN: if (RD_FLD(instr, INSTR_I) == 0) { - if (!labels) - printf("RETURN r%d + r%d", RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_RS2)); - else - printf("RETURN l%d + l%d", labelrs1, labelrs2); + printf("return "); + sparc_printop_rs1(instr, labelrs1); + printf("+"); + sparc_printop_rs2(instr, labelrs2); } else { - if (!labels) - printf("RETURN r%d + %d", RD_FLD(instr, INSTR_RS1), SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - else - printf("RETURN l%d + %d", labelrs1, SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + printf("return "); + sparc_printop_rs1(instr, labelrs1); + printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); } return; case OP3_SAVE: if (RD_FLD(instr, INSTR_I) == 0) { - if (!labels) - printf("save r%d , r%d, r%d", RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_RS2), RD_FLD(instr, INSTR_RD)); - else - printf("save l%d , l%d, l%d", labelrs1, labelrs2, labelrd); - } + printf("save "); + sparc_printop_rs1(instr, labelrs1); + printf(", "); + sparc_printop_rs2(instr, labelrs2); + printf(", "); + sparc_printop_rrd(instr, labelrd); + } else { - if (!labels) - printf("save r%d , %d, r%d", RD_FLD(instr, INSTR_RS1), SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)), RD_FLD(instr, INSTR_RD)); - else - printf("save l%d , %d, l%d", labelrs1, SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)), labelrd); + printf("save "); + sparc_printop_rs1(instr, labelrs1); + printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + sparc_printop_rrd(instr, labelrd); } return; case OP3_RESTORE: if (RD_FLD(instr, INSTR_I) == 0) { - if (!labels) - printf("RESTORE r%d , r%d, r%d", RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_RS2), RD_FLD(instr, INSTR_RD)); - else - printf("RESTORE l%d , l%d, l%d", labelrs1, labelrs2, labelrd); - } + printf("restore "); + sparc_printop_rs1(instr, labelrs1); + printf(", "); + sparc_printop_rs2(instr, labelrs2); + printf(", "); + sparc_printop_rrd(instr, labelrd); + } else { - if (!labels) - printf("RESTORE r%d , %d, r%d", RD_FLD(instr, INSTR_RS1), SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)), RD_FLD(instr, INSTR_RD)); - else - printf("RESTORE l04%d , %d, l04%d",labelrs1, SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)), labelrd); - + printf("restore "); + sparc_printop_rs1(instr, labelrs1); + printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + sparc_printop_rrd(instr, labelrd); } return; @@ -442,21 +465,52 @@ assert(0); } -void sparc_printldst(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd , int labelccf) +void sparc_printload(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd , int labelccf) { if (RD_FLD(instr, INSTR_I)==0) { + printf("%s ", basename); if (!labels) - printf("%s r%d <- r%d , r%d", basename,RD_FLD(instr, INSTR_RD), RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_RS2)); - else - printf("%s l04%d <- l%d , l%d", basename, labelrd, labelrs1, labelrs2); + { + sparc_printop_rrd(instr, labelrd); + printf(", "); + } + sparc_printop_rs1(instr, labelrs1); + printf("+"); + sparc_printop_rs2(instr, labelrs2); } else { + printf("%s ", basename); if (!labels) - printf("%s r%d <- r%d , %d",basename, RD_FLD(instr, INSTR_RD), RD_FLD(instr, INSTR_RS1), SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - else - printf("%s l%d <- l%d, l%d", basename, labelrd, labelrs1,SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + { + sparc_printop_rrd(instr, labelrd); + printf(", "); + } + sparc_printop_rs1(instr, labelrs1); + printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + } +} + +void sparc_printstore(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd , int labelccf) +{ + if (RD_FLD(instr, INSTR_I)==0) + { + printf("%s ", basename); + sparc_printop_rrd(instr, labelrd); + printf(", "); + sparc_printop_rs1(instr, labelrs1); + printf("+"); + sparc_printop_rs2(instr, labelrs2); + + } + else + { + printf("%s ", basename); + sparc_printop_rrd(instr, labelrd); + printf(", "); + sparc_printop_rs1(instr, labelrs1); + printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); } } void sparc_print3(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) @@ -470,51 +524,51 @@ { //OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13} case OP3_LDSTUB: - sparc_printldst("LDSTUB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printload("LDSTUB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STB: - sparc_printldst("STB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printstore("STB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STH: - sparc_printldst("STH", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printstore("STH", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STW: - sparc_printldst("STW", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printstore("STW", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STX: - sparc_printldst("STX", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printstore("STX", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDSB: - sparc_printldst("LDSB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printload("LDSB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDSH: - sparc_printldst("LDSH", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printload("LDSH", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDSW: - sparc_printldst("LDSW", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printload("LDSW", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDUB: - sparc_printldst("LDUB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printload("LDUB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDUH: - sparc_printldst("LDUH", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printload("LDUH", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDUW: - sparc_printldst("LDUW", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printload("LDUW", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDX: - sparc_printldst("LDX", instr,labels,labelrs1, labelrs2, labelrd, labelccf); + sparc_printload("LDX", instr,labels,labelrs1, labelrs2, labelrd, labelccf); return; case OP3_CASA: @@ -588,3 +642,6 @@ else if (RD_FLD(instr,INSTR_OP)==OP_3) sparc_print3(instr,false,0, 0, 0, 0 ); } + + + Index: llvm/lib/Reoptimizer/BinInterface/sparcdis.h diff -u llvm/lib/Reoptimizer/BinInterface/sparcdis.h:1.3 llvm/lib/Reoptimizer/BinInterface/sparcdis.h:1.4 --- llvm/lib/Reoptimizer/BinInterface/sparcdis.h:1.3 Wed Nov 27 20:20:42 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcdis.h Sat Dec 14 19:32:18 2002 @@ -18,17 +18,19 @@ // // 2002 Cameron Buschardt //***************************************************************************** - -#ifndef __SPARCDIS__ -#define __SPARCDIS__ -// Conventional Disassembly. Prints instruction (no newline) -void sparc_print(unsigned instr); - -// Pseudo disasm -// uses the integers in labelrs1, labelrs2, labelrd, and labelccf as -// gen labels for the parameter sources -// instead of printing rxx for rs1, it will print l__labelrs1__ + +#ifndef __SPARCDIS__ +#define __SPARCDIS__ +// Conventional Disassembly. Prints instruction (no newline) +void sparc_print(unsigned instr); + +// Pseudo disasm +// uses the integers in labelrs1, labelrs2, labelrd, and labelccf as +// gen labels for the parameter sources +// instead of printing rxx for rs1, it will print l__labelrs1__ void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf); - - -#endif \ No newline at end of file + + +#endif + + From buschard at cs.uiuc.edu Sat Dec 14 19:42:01 2002 From: buschard at cs.uiuc.edu (Cameron Buschardt) Date: Sat Dec 14 19:42:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/analyze.cpp salloc.h binproc.cpp Message-ID: <200212150141.TAA18394@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/BinInterface: analyze.cpp updated: 1.5 -> 1.6 salloc.h updated: 1.2 -> 1.3 binproc.cpp (r1.3) removed --- Log message: Remove binproc.cpp tool - since I have checked in the preprocessed sparc9.h file --- Diffs of the changes: Index: llvm/lib/Reoptimizer/BinInterface/analyze.cpp diff -u llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.5 llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.6 --- llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.5 Sat Dec 14 19:30:54 2002 +++ llvm/lib/Reoptimizer/BinInterface/analyze.cpp Sat Dec 14 19:40:40 2002 @@ -57,6 +57,7 @@ assert(0); return 0; } + return 0; } // @@ -160,6 +161,7 @@ assert(0); } + return 0; } @@ -217,6 +219,7 @@ printf("Unknown OP_3: OP3 = %08X\n", RD_FLD(instr, INSTR_OP3)); assert(0); } + return 0; } unsigned sparc_analyze_full(unsigned instr) @@ -231,6 +234,7 @@ return IF_CALL; // Call instruction not seen as branch // in that control flow change is transparent // to trace + return 0; } unsigned sparc_analyze(unsigned instr) Index: llvm/lib/Reoptimizer/BinInterface/salloc.h diff -u llvm/lib/Reoptimizer/BinInterface/salloc.h:1.2 llvm/lib/Reoptimizer/BinInterface/salloc.h:1.3 --- llvm/lib/Reoptimizer/BinInterface/salloc.h:1.2 Sat Dec 14 19:31:41 2002 +++ llvm/lib/Reoptimizer/BinInterface/salloc.h Sat Dec 14 19:40:48 2002 @@ -24,6 +24,7 @@ virtual void*alloc(unsigned size) = 0; virtual void free(void * block) = 0; virtual void*resize(void * block , unsigned newsize) = 0; + virtual ~Allocator() {} }; From buschard at cs.uiuc.edu Sat Dec 14 20:34:00 2002 From: buschard at cs.uiuc.edu (Cameron Buschardt) Date: Sat Dec 14 20:34:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/sparc9.cpp fvector.h Message-ID: <200212150233.UAA18615@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/BinInterface: sparc9.cpp added (r1.1) fvector.h updated: 1.4 -> 1.5 --- Log message: --- Diffs of the changes: Index: llvm/lib/Reoptimizer/BinInterface/fvector.h diff -u llvm/lib/Reoptimizer/BinInterface/fvector.h:1.4 llvm/lib/Reoptimizer/BinInterface/fvector.h:1.5 --- llvm/lib/Reoptimizer/BinInterface/fvector.h:1.4 Sat Dec 14 19:31:40 2002 +++ llvm/lib/Reoptimizer/BinInterface/fvector.h Sat Dec 14 20:04:27 2002 @@ -142,7 +142,7 @@ } v_end = v_begin+amt; } - T& operator[] (unsigned n) { printf("write 0x%08X\n", v_begin+n); + T& operator[] (unsigned n) { return v_begin[n]; } const T & operator[] (unsigned n) const { return v_begin[n]; } From lattner at cs.uiuc.edu Sat Dec 14 21:51:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Dec 14 21:51:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/Reassociate.cpp Message-ID: <200212150350.VAA02909@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: Reassociate.cpp updated: 1.13 -> 1.14 --- Log message: Minor changes: * Reword comment to make more clear * Don't print out BB's after modification made * Don't delete and new an instruction when we need to move something, just move it. --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/Reassociate.cpp diff -u llvm/lib/Transforms/Scalar/Reassociate.cpp:1.13 llvm/lib/Transforms/Scalar/Reassociate.cpp:1.14 --- llvm/lib/Transforms/Scalar/Reassociate.cpp:1.13 Thu Oct 31 11:12:59 2002 +++ llvm/lib/Transforms/Scalar/Reassociate.cpp Sat Dec 14 21:49:50 2002 @@ -68,7 +68,7 @@ // If this is an expression, return the MAX(rank(LHS), rank(RHS)) so that we // can reassociate expressions for code motion! Since we do not recurse for // PHI nodes, we cannot have infinite recursion here, because there cannot - // be loops in the value graph (except for PHI nodes). + // be loops in the value graph that do not go through PHI nodes. // if (I->getOpcode() == Instruction::PHINode || I->getOpcode() == Instruction::Alloca || @@ -106,7 +106,8 @@ std::swap(LHSRank, RHSRank); Changed = true; ++NumSwapped; - DEBUG(std::cerr << "Transposed: " << I << " Result BB: " << I->getParent()); + DEBUG(std::cerr << "Transposed: " << I + /* << " Result BB: " << I->getParent()*/); } // If the LHS is the same operator as the current one is, and if we are the @@ -124,28 +125,20 @@ // Convert ((a + 12) + 10) into (a + (12 + 10)) I->setOperand(0, LHSI->getOperand(TakeOp)); + LHSI->setOperand(TakeOp, RHS); + I->setOperand(1, LHSI); // Move the LHS expression forward, to ensure that it is dominated by // its operands. - std::string Name = LHSI->getName(); - LHSI->setName(""); - BinaryOperator *NewLHS = - BinaryOperator::create(LHSI->getOpcode(), - LHSI->getOperand(0), LHSI->getOperand(1), - Name, I); - - NewLHS->setOperand(TakeOp, RHS); - I->setOperand(1, NewLHS); - - assert(LHSI->use_size() == 0 && "References to LHS shouldn't exist!"); - LHSI->getParent()->getInstList().erase(LHSI); + LHSI->getParent()->getInstList().remove(LHSI); + I->getParent()->getInstList().insert(I, LHSI); ++NumChanged; - DEBUG(std::cerr << "Reassociated: " << I << " Result BB: " - << I->getParent()); + DEBUG(std::cerr << "Reassociated: " << I/* << " Result BB: " + << I->getParent()*/); // Since we modified the RHS instruction, make sure that we recheck it. - ReassociateExpr(NewLHS); + ReassociateExpr(LHSI); return true; } } @@ -195,6 +188,7 @@ bool Changed = false; for (BasicBlock::iterator BI = BB->begin(); BI != BB->end(); ++BI) { + DEBUG(std::cerr << "Processing: " << *BI); if (BI->getOpcode() == Instruction::Sub && !BinaryOperator::isNeg(BI)) { // Convert a subtract into an add and a neg instruction... so that sub // instructions can be commuted with other add instructions... @@ -218,7 +212,7 @@ New->setOperand(1, NegateValue(New->getOperand(1), BI)); Changed = true; - DEBUG(std::cerr << "Negated: " << New << " Result BB: " << BB); + DEBUG(std::cerr << "Negated: " << New /*<< " Result BB: " << BB*/); } // If this instruction is a commutative binary operator, and the ranks of @@ -248,7 +242,7 @@ I = Tmp; ++NumLinear; Changed = true; - DEBUG(std::cerr << "Linearized: " << I << " Result BB: " << BB); + DEBUG(std::cerr << "Linearized: " << I/* << " Result BB: " << BB*/); } // Make sure that this expression is correctly reassociated with respect From lattner at cs.uiuc.edu Sat Dec 14 21:57:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Dec 14 21:57:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/Reassociate.cpp Message-ID: <200212150356.VAA02995@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: Reassociate.cpp updated: 1.14 -> 1.15 --- Log message: Fix a huge performance problem in reassociate by introducing a rank map cache for instruction ranks --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/Reassociate.cpp diff -u llvm/lib/Transforms/Scalar/Reassociate.cpp:1.14 llvm/lib/Transforms/Scalar/Reassociate.cpp:1.15 --- llvm/lib/Transforms/Scalar/Reassociate.cpp:1.14 Sat Dec 14 21:49:50 2002 +++ llvm/lib/Transforms/Scalar/Reassociate.cpp Sat Dec 14 21:56:00 2002 @@ -36,6 +36,7 @@ class Reassociate : public FunctionPass { std::map RankMap; + std::map InstRankMap; public: bool runOnFunction(Function &F); @@ -76,12 +77,16 @@ I->hasSideEffects()) return RankMap[I->getParent()]; + unsigned &CachedRank = InstRankMap[I]; + if (CachedRank) return CachedRank; // Rank already known? + + // If not, compute it! unsigned Rank = 0, MaxRank = RankMap[I->getParent()]; for (unsigned i = 0, e = I->getNumOperands(); i != e && Rank != MaxRank; ++i) Rank = std::max(Rank, getRank(I->getOperand(i))); - return Rank; + return CachedRank = Rank; } // Otherwise it's a global or constant, rank 0. @@ -267,5 +272,6 @@ // We are done with the rank map... RankMap.clear(); + InstRankMap.clear(); return Changed; } From lattner at cs.uiuc.edu Sat Dec 14 22:24:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Dec 14 22:24:01 2002 Subject: [llvm-commits] CVS: llvm/www/www-index.html Message-ID: <200212150423.WAA08687@tank.cs.uiuc.edu> Changes in directory llvm/www: www-index.html updated: 1.10 -> 1.11 --- Log message: Add ms thesis to page --- Diffs of the changes: Index: llvm/www/www-index.html diff -u llvm/www/www-index.html:1.10 llvm/www/www-index.html:1.11 --- llvm/www/www-index.html:1.10 Fri Nov 22 13:09:35 2002 +++ llvm/www/www-index.html Sat Dec 14 22:23:41 2002 @@ -98,11 +98,32 @@ Publications & - Technical Reports + Papers
    +
  1. "LLVM: + An Infrastructure for Multi-Stage + Optimization"
    + Chris Lattner. Masters Thesis, Dec. 2002
  2. +
  3. "Ensuring + Code Safety Without Runtime Checks for + Real-Time Control Systems"
    + Sumant Kowshik, Dinakar Dhurjati, and + Vikram Adve. Proc. Int’l Conf. on + Compilers, Architecture and Synthesis for + Embedded Systems (CASES02), Grenoble, + France, Oct. 2002.
  4. +
  5. "The + LLVM Instruction Set and Compilation + Strategy"
    + Chris Lattner & Vikram Adve, Technical + Report #UIUCDCS-R-2002-2292, Computer + Science Dept., Univ. of Illinois, + Aug. 2002.
    +
  6. "Automatic Pool Allocation for Disjoint Data @@ -114,23 +135,6 @@ Berlin, Germany, June 2002.
    (
    Presentation).
  7. -
  8. "The - LLVM Instruction Set and Compilation - Strategy"
    - Chris Lattner & Vikram Adve, Technical - Report #UIUCDCS-R-2002-2292, Computer - Science Dept., Univ. of Illinois, - Aug. 2002.
    -
  9. -
  10. "Ensuring - Code Safety Without Runtime Checks for - Real-Time Control Systems"
    - Sumant Kowshik, Dinakar Dhurjati, and - Vikram Adve. Proc. Int’l Conf. on - Compilers, Architecture and Synthesis for - Embedded Systems (CASES02), Grenoble, - France, Oct. 2002.

@@ -186,6 +190,13 @@ + + + + + From lattner at cs.uiuc.edu Sun Dec 15 01:56:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 01:56:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-cast.ll Message-ID: <200212150755.BAA06669@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-cast.ll added (r1.1) --- Log message: New testcase for bool support --- Diffs of the changes: From lattner at cs.uiuc.edu Sun Dec 15 02:02:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 02:02:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineInstr.h MachineInstrBuilder.h Message-ID: <200212150801.CAA06798@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineInstr.h updated: 1.90 -> 1.91 MachineInstrBuilder.h updated: 1.8 -> 1.9 --- Log message: Add capability to have a MachineBasicBlock as an operand to a MachineInstr Add a bunch of methods to MachineOperand is* to reduce usage of MO_foo --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineInstr.h diff -u llvm/include/llvm/CodeGen/MachineInstr.h:1.90 llvm/include/llvm/CodeGen/MachineInstr.h:1.91 --- llvm/include/llvm/CodeGen/MachineInstr.h:1.90 Fri Nov 22 16:40:52 2002 +++ llvm/include/llvm/CodeGen/MachineInstr.h Sun Dec 15 02:01:02 2002 @@ -79,6 +79,7 @@ MO_SignExtendedImmed, MO_UnextendedImmed, MO_PCRelativeDisp, + MO_MachineBasicBlock, // MachineBasicBlock reference }; private: @@ -98,23 +99,25 @@ // including hidden operands required for // the generated machine code. int64_t immedVal; // constant value for an explicit constant + + MachineBasicBlock *MBB; // For MO_MachineBasicBlock type }; - MachineOperandType opType:8; // Pack into 8 bits efficiently after flags. char flags; // see bit field definitions above + MachineOperandType opType:8; // Pack into 8 bits efficiently after flags. int regNum; // register number for an explicit register // will be set for a value after reg allocation private: MachineOperand() : immedVal(0), - opType(MO_VirtualRegister), flags(0), + opType(MO_VirtualRegister), regNum(-1) {} MachineOperand(int64_t ImmVal, MachineOperandType OpTy) : immedVal(ImmVal), - opType(OpTy), flags(0), + opType(OpTy), regNum(-1) {} MachineOperand(int Reg, MachineOperandType OpTy, MOTy::UseType UseTy) @@ -139,11 +142,14 @@ } } + MachineOperand(MachineBasicBlock *mbb) + : MBB(mbb), flags(0), opType(MO_MachineBasicBlock), regNum(-1) {} + public: MachineOperand(const MachineOperand &M) : immedVal(M.immedVal), - opType(M.opType), flags(M.flags), + opType(M.opType), regNum(M.regNum) {} ~MachineOperand() {} @@ -163,8 +169,17 @@ return (opType == MO_VirtualRegister || opType == MO_MachineRegister) && regNum >= MRegisterInfo::FirstVirtualRegister; } - + bool isPhysicalRegister() const { + return (opType == MO_VirtualRegister || opType == MO_MachineRegister) + && regNum < MRegisterInfo::FirstVirtualRegister; + } + bool isRegister() const { return isVirtualRegister() || isPhysicalRegister();} bool isMachineRegister() const { return !isVirtualRegister(); } + bool isMachineBasicBlock() const { return opType == MO_MachineBasicBlock; } + bool isPCRelativeDisp() const { return opType == MO_PCRelativeDisp; } + bool isImmediate() const { + return opType == MO_SignExtendedImmed || opType == MO_UnextendedImmed; + } inline Value* getVRegValue () const { assert(opType == MO_VirtualRegister || opType == MO_CCRegister || @@ -180,9 +195,14 @@ return regNum; } inline int64_t getImmedValue () const { - assert(opType == MO_SignExtendedImmed || opType == MO_UnextendedImmed); + assert(isImmediate()); return immedVal; } + MachineBasicBlock *getMachineBasicBlock() const { + assert(isMachineBasicBlock() && "Can't get MBB in non-MBB operand!"); + return MBB; + } + bool opIsDef () const { return flags & DEFFLAG; } bool opIsDefAndUse () const { return flags & DEFUSEFLAG; } bool opHiBits32 () const { return flags & HIFLAG32; } @@ -482,6 +502,11 @@ MachineOperand::MO_SignExtendedImmed)); } + void addMachineBasicBlockOperand(MachineBasicBlock *MBB) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(MBB)); + } unsigned substituteValue(const Value* oldVal, Value* newVal, bool defsOnly = true); Index: llvm/include/llvm/CodeGen/MachineInstrBuilder.h diff -u llvm/include/llvm/CodeGen/MachineInstrBuilder.h:1.8 llvm/include/llvm/CodeGen/MachineInstrBuilder.h:1.9 --- llvm/include/llvm/CodeGen/MachineInstrBuilder.h:1.8 Fri Dec 13 03:33:06 2002 +++ llvm/include/llvm/CodeGen/MachineInstrBuilder.h Sun Dec 15 02:01:02 2002 @@ -81,6 +81,11 @@ MI->addZeroExtImmOperand(Val); return *this; } + + const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB) const { + MI->addMachineBasicBlockOperand(MBB); + return *this; + } }; /// BuildMI - Builder interface. Specify how to create the initial instruction From lattner at cs.uiuc.edu Sun Dec 15 02:02:05 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 02:02:05 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Printer.cpp MachineCodeEmitter.cpp Message-ID: <200212150801.CAA06821@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Printer.cpp updated: 1.27 -> 1.28 MachineCodeEmitter.cpp updated: 1.11 -> 1.12 --- Log message: Use MachineOperand::isFoo methods instead of our own global functions --- Diffs of the changes: Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.27 llvm/lib/Target/X86/Printer.cpp:1.28 --- llvm/lib/Target/X86/Printer.cpp:1.27 Fri Dec 13 03:59:26 2002 +++ llvm/lib/Target/X86/Printer.cpp Sun Dec 15 02:01:39 2002 @@ -66,30 +66,16 @@ return false; } -static bool isReg(const MachineOperand &MO) { - return MO.getType() == MachineOperand::MO_VirtualRegister || - MO.getType() == MachineOperand::MO_MachineRegister; -} - -static bool isImmediate(const MachineOperand &MO) { - return MO.getType() == MachineOperand::MO_SignExtendedImmed || - MO.getType() == MachineOperand::MO_UnextendedImmed; -} - -static bool isPCRelativeDisp(const MachineOperand &MO) { - return MO.getType() == MachineOperand::MO_PCRelativeDisp; -} - static bool isScale(const MachineOperand &MO) { - return isImmediate(MO) && + return MO.isImmediate() && (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 || MO.getImmedValue() == 4 || MO.getImmedValue() == 8); } static bool isMem(const MachineInstr *MI, unsigned Op) { return Op+4 <= MI->getNumOperands() && - isReg(MI->getOperand(Op )) && isScale(MI->getOperand(Op+1)) && - isReg(MI->getOperand(Op+2)) && isImmediate(MI->getOperand(Op+3)); + MI->getOperand(Op ).isRegister() &&isScale(MI->getOperand(Op+1)) && + MI->getOperand(Op+2).isRegister() &&MI->getOperand(Op+3).isImmediate(); } static void printOp(std::ostream &O, const MachineOperand &MO, @@ -190,7 +176,7 @@ // 2. jmp foo - PC relative displacement operand // assert(MI->getNumOperands() == 0 || - (MI->getNumOperands() == 1 && isPCRelativeDisp(MI->getOperand(0))) && + (MI->getNumOperands() == 1 && MI->getOperand(0).isPCRelativeDisp())&& "Illegal raw instruction!"); O << getName(MI->getOpCode()) << " "; @@ -208,11 +194,11 @@ // an LLVM value, to represent, for example, loading the address of a global // into a register. // - assert(isReg(MI->getOperand(0)) && + assert(MI->getOperand(0).isRegister() && (MI->getNumOperands() == 1 || (MI->getNumOperands() == 2 && (MI->getOperand(1).getVRegValueOrNull() || - isImmediate(MI->getOperand(1))))) && + MI->getOperand(1).isImmediate()))) && "Illegal form for AddRegFrm instruction!"); unsigned Reg = MI->getOperand(0).getReg(); @@ -237,10 +223,10 @@ // // 2 Operands: this is for things like mov that do not read a second input // - assert(isReg(MI->getOperand(0)) && + assert(MI->getOperand(0).isRegister() && (MI->getNumOperands() == 2 || - (MI->getNumOperands() == 3 && isReg(MI->getOperand(1)))) && - isReg(MI->getOperand(MI->getNumOperands()-1)) + (MI->getNumOperands() == 3 && MI->getOperand(1).isRegister())) && + MI->getOperand(MI->getNumOperands()-1).isRegister() && "Bad format for MRMDestReg!"); if (MI->getNumOperands() == 3 && MI->getOperand(0).getReg() != MI->getOperand(1).getReg()) @@ -259,7 +245,7 @@ // register reference for the mod/rm field, it's a memory reference. // assert(isMem(MI, 0) && MI->getNumOperands() == 4+1 && - isReg(MI->getOperand(4)) && "Bad format for MRMDestMem!"); + MI->getOperand(4).isRegister() && "Bad format for MRMDestMem!"); O << getName(MI->getOpCode()) << " " << sizePtr (Desc) << " "; printMemReference(O, MI, 0, RI); @@ -279,10 +265,10 @@ // // 2 Operands: this is for things like mov that do not read a second input // - assert(isReg(MI->getOperand(0)) && - isReg(MI->getOperand(1)) && + assert(MI->getOperand(0).isRegister() && + MI->getOperand(1).isRegister() && (MI->getNumOperands() == 2 || - (MI->getNumOperands() == 3 && isReg(MI->getOperand(2)))) + (MI->getNumOperands() == 3 && MI->getOperand(2).isRegister())) && "Bad format for MRMDestReg!"); if (MI->getNumOperands() == 3 && MI->getOperand(0).getReg() != MI->getOperand(1).getReg()) @@ -300,9 +286,9 @@ // These instructions are the same as MRMSrcReg, but instead of having a // register reference for the mod/rm field, it's a memory reference. // - assert(isReg(MI->getOperand(0)) && + assert(MI->getOperand(0).isRegister() && (MI->getNumOperands() == 1+4 && isMem(MI, 1)) || - (MI->getNumOperands() == 2+4 && isReg(MI->getOperand(1)) && + (MI->getNumOperands() == 2+4 && MI->getOperand(1).isRegister() && isMem(MI, 2)) && "Bad format for MRMDestReg!"); if (MI->getNumOperands() == 2+4 && @@ -328,21 +314,21 @@ // 3. sbb rdest, rinput, immediate [rdest = rinput] // assert(MI->getNumOperands() > 0 && MI->getNumOperands() < 4 && - isReg(MI->getOperand(0)) && "Bad MRMSxR format!"); + MI->getOperand(0).isRegister() && "Bad MRMSxR format!"); assert((MI->getNumOperands() != 2 || - isReg(MI->getOperand(1)) || isImmediate(MI->getOperand(1))) && + MI->getOperand(1).isRegister() || MI->getOperand(1).isImmediate())&& "Bad MRMSxR format!"); assert((MI->getNumOperands() < 3 || - (isReg(MI->getOperand(1)) && isImmediate(MI->getOperand(2)))) && + (MI->getOperand(1).isRegister() && MI->getOperand(2).isImmediate())) && "Bad MRMSxR format!"); - if (MI->getNumOperands() > 1 && isReg(MI->getOperand(1)) && + if (MI->getNumOperands() > 1 && MI->getOperand(1).isRegister() && MI->getOperand(0).getReg() != MI->getOperand(1).getReg()) O << "**"; O << getName(MI->getOpCode()) << " "; printOp(O, MI->getOperand(0), RI); - if (isImmediate(MI->getOperand(MI->getNumOperands()-1))) { + if (MI->getOperand(MI->getNumOperands()-1).isImmediate()) { O << ", "; printOp(O, MI->getOperand(MI->getNumOperands()-1), RI); } Index: llvm/lib/Target/X86/MachineCodeEmitter.cpp diff -u llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.11 llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.12 --- llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.11 Fri Dec 13 01:56:18 2002 +++ llvm/lib/Target/X86/MachineCodeEmitter.cpp Sun Dec 15 02:01:39 2002 @@ -200,11 +200,6 @@ } } -static bool isImmediate(const MachineOperand &MO) { - return MO.getType() == MachineOperand::MO_SignExtendedImmed || - MO.getType() == MachineOperand::MO_UnextendedImmed; -} - unsigned sizeOfPtr (const MachineInstrDescriptor &Desc) { switch (Desc.TSFlags & X86II::ArgMask) { case X86II::Arg8: return 1; @@ -276,12 +271,10 @@ emitRegModRMByte(MI.getOperand(0).getReg(), (Desc.TSFlags & X86II::FormMask)-X86II::MRMS0r); - if (isImmediate(MI.getOperand(MI.getNumOperands()-1))) { + if (MI.getOperand(MI.getNumOperands()-1).isImmediate()) { unsigned Size = sizeOfPtr(Desc); emitConstant(MI.getOperand(MI.getNumOperands()-1).getImmedValue(), Size); } break; - - } } From lattner at cs.uiuc.edu Sun Dec 15 02:03:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 02:03:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212150802.CAA06835@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.68 -> 1.69 --- Log message: Add support to cast from a bool type Add support for boolean constants add getClassB method --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.68 llvm/lib/Target/X86/InstSelectSimple.cpp:1.69 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.68 Fri Dec 13 08:13:27 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Sun Dec 15 02:02:15 2002 @@ -273,6 +273,12 @@ } } +// getClassB - Just like getClass, but treat boolean values as bytes. +static inline TypeClass getClassB(const Type *Ty) { + if (Ty == Type::BoolTy) return cByte; + return getClass(Ty); +} + /// copyConstantToRegister - Output the instructions required to put the /// specified constant into the specified register. @@ -292,14 +298,16 @@ } if (C->getType()->isIntegral()) { - unsigned Class = getClass(C->getType()); + unsigned Class = getClassB(C->getType()); assert(Class != 3 && "Type not handled yet!"); static const unsigned IntegralOpcodeTab[] = { X86::MOVir8, X86::MOVir16, X86::MOVir32 }; - if (C->getType()->isSigned()) { + if (C->getType() == Type::BoolTy) { + BMI(MBB, IP, X86::MOVir8, 1, R).addZImm(C == ConstantBool::True); + } else if (C->getType()->isSigned()) { ConstantSInt *CSI = cast(C); BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addSImm(CSI->getValue()); } else { @@ -348,9 +356,7 @@ while ((*PI)->getOpcode() == X86::PHI) ++PI; MI->addRegOperand(getReg(PN->getIncomingValue(i), PredMBB, PI)); - - // FIXME: Pass in the MachineBasicBlocks instead of the basic blocks... - MI->addPCDispOperand(PN->getIncomingBlock(i)); // PredMBB + MI->addMachineBasicBlockOperand(PredMBB); } } } @@ -878,7 +884,7 @@ // 2) Implement casts between values of the same type class (as determined // by getClass) by using a register-to-register move. - unsigned srcClass = sourceType == Type::BoolTy ? cByte : getClass(sourceType); + unsigned srcClass = getClassB(sourceType); unsigned targClass = getClass (targetType); static const unsigned regRegMove[] = { X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 From lattner at cs.uiuc.edu Sun Dec 15 02:04:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 02:04:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212150803.CAA06847@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.12 -> 1.13 --- Log message: Fix borkness with not using MachineBasicBlocks in PHI nodes --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.12 llvm/lib/CodeGen/RegAllocSimple.cpp:1.13 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.12 Fri Dec 13 06:33:31 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 02:02:51 2002 @@ -267,18 +267,7 @@ // Get the MachineBasicBlock equivalent of the BasicBlock that is the // source path the phi - BasicBlock *opBB = - cast(MI->getOperand(i).getVRegValue()); - MachineBasicBlock *opBlock = NULL; - for (MachineFunction::iterator opFi = Fn.begin(), opFe = Fn.end(); - opFi != opFe; ++opFi) - { - if (opFi->getBasicBlock() == opBB) { - opBlock = opFi; break; - } - } - assert(opBlock && "MachineBasicBlock object not found for specified block!"); - + MachineBasicBlock *opBlock = MI->getOperand(i).getMachineBasicBlock(); MachineBasicBlock::iterator opI = opBlock->end(); MachineInstr *opMI = *(--opI); const MachineInstrInfo &MII = TM.getInstrInfo(); From buschard at cs.uiuc.edu Sun Dec 15 05:09:01 2002 From: buschard at cs.uiuc.edu (Cameron Buschardt) Date: Sun Dec 15 05:09:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/analyze.cpp analyze.h bitmath.h construct.cpp emit.cpp fvector.h regmask.h salloc.cpp salloc.h select.cpp sparc9.cpp sparc9.h sparcbin.cpp sparcbin.h sparcdis.cpp sparcdis.h sparcpriv.h test.cpp machine.h Message-ID: <200212151108.FAA21056@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/BinInterface: analyze.cpp updated: 1.6 -> 1.7 analyze.h updated: 1.4 -> 1.5 bitmath.h updated: 1.4 -> 1.5 construct.cpp updated: 1.1 -> 1.2 emit.cpp updated: 1.1 -> 1.2 fvector.h updated: 1.5 -> 1.6 regmask.h updated: 1.1 -> 1.2 salloc.cpp updated: 1.2 -> 1.3 salloc.h updated: 1.3 -> 1.4 select.cpp updated: 1.1 -> 1.2 sparc9.cpp updated: 1.1 -> 1.2 sparc9.h updated: 1.7 -> 1.8 sparcbin.cpp updated: 1.2 -> 1.3 sparcbin.h updated: 1.2 -> 1.3 sparcdis.cpp updated: 1.5 -> 1.6 sparcdis.h updated: 1.4 -> 1.5 sparcpriv.h updated: 1.1 -> 1.2 test.cpp updated: 1.1 -> 1.2 machine.h (r1.3) removed --- Log message: Formatted code, removed debug printouts, fixed compatibility with GCC 3.2 when outputting 64-bit code. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/BinInterface/analyze.cpp diff -u llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.6 llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.7 --- llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.6 Sat Dec 14 19:40:40 2002 +++ llvm/lib/Reoptimizer/BinInterface/analyze.cpp Sun Dec 15 05:06:55 2002 @@ -1,5 +1,5 @@ //***************************************************************************** -// SPARC Instruction Analysis +// SPARC Instruction Analysis // // Analysis API Implementation // @@ -17,273 +17,343 @@ #include #include -#include "sparc9.h" // SPARC 9 opcode and field definitions -#include "bitmath.h" -#include "analyze.h" // API library +#include "sparc9.h" // SPARC 9 opcode and field definitions +#include "bitmath.h" // Binary arithmatic library +#include "analyze.h" // Defintion of analysis interface #include +//***************************************************************************** +// unsigned sparc_analyzebr(unsigned instr) // // Analyze instructions with OP field set to OP_BRANCH // (note not all of these instructions are branches!) // +// +// Returns a mask stating which parameters (RS1/RS2/etc) are present +// and whether we write to CC, etc. See analyze.h +// +//***************************************************************************** + unsigned sparc_analyzebr(unsigned instr) { - // look at the OP2 field - if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI) - { - // The sethi instruction zeroes the register - // and loads the immediate into bits 10->31 - if (RD_FLD(instr, INSTR_RD) == 0) - return 0; // This is the special encoding for NOP - else - return IF_RD | IF_W_RD; - } - else if (RD_FLD(instr, INSTR_OP2)==OP2_BICC) - { - // Branch on integer condition code - return IF_RCC | IF_BR; - } - else if (RD_FLD(instr, INSTR_OP2)==OP2_BPR) - { - // Branch on integer register with prediction - return IF_RCC | IF_RS1 | IF_R_RS1; - } - else{ - // There are a few opcodes missing from this field, - // if we run into any of them we can add support - // most appear to be systems level instructions - - printf("Unknown:OP=0b00 OP2 = 0x%04X\n", RD_FLD(instr, INSTR_OP2)); - assert(0); - return 0; - } + // look at the OP2 field + if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI) + { + // The sethi instruction zeroes the register + // and loads the immediate into bits 10->31 + if (RD_FLD(instr, INSTR_RD) == 0) + return 0; // This is the special encoding for NOP + else + return IF_RD | IF_W_RD; + } + else if (RD_FLD(instr, INSTR_OP2)==OP2_BICC) + { + // Branch on integer condition code + return IF_RCC | IF_BR; + } + else if (RD_FLD(instr, INSTR_OP2)==OP2_BPR) + { + // Branch on integer register with prediction + return IF_RCC | IF_RS1 | IF_R_RS1; + } + else{ + // There are a few opcodes missing from this field, + // if we run into any of them we can add support + // most appear to be systems level instructions + + printf("Unknown:OP=0b00 OP2 = 0x%04X\n", RD_FLD(instr, INSTR_OP2)); + assert(0); return 0; + } + return 0; } +//***************************************************************************** +// unsigned sparc_analyze_c2(unsigned instr) // -// Analyze instructions with OP field set to 2 +// Analyze instructions with OP field set to OP_2 // +//***************************************************************************** + unsigned sparc_analyze_c2(unsigned instr) { - switch(RD_FLD(instr, INSTR_OP3)) - { - case OP3_DONERETRY: - assert(0); // This appears to be a system instruction - // either way though it acts like a branch - // and should NOT appear in an trace - return 0; - - case OP3_FCMP: - case OP3_FPU: - assert(0); // TODO: Add support when we do floating point - // support! - return 0; - - case OP3_FLUSHW: //OP=OP_2 I = 0 - return 0; // Flush has no negative side effects - - case OP3_FLUSH: //OP=OP_2 RS1 {I=0 -> IF_RS2, I=1->simm13} - if (RD_FLD(instr, INSTR_I) == 0) - return IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2; - else - return IF_RS1 | IF_R_RS1; - - case OP3_JMPL: //OP=OP_2 RD, IF_RS1 {I=0-> IF_RS2, I=1->SIMM13} - case OP3_ADD: - case OP3_AND: - case OP3_OR: - case OP3_XOR: - case OP3_SUB: - case OP3_ANDN: - case OP3_ORN: - case OP3_XNOR: - case OP3_MULX: - case OP3_SDIVX: - case OP3_UDIVX: - case OP3_SLL: - case OP3_SRL: - case OP3_SRA: - case OP3_SAVE: - case OP3_RETURN: - case OP3_RESTORE: - if (RD_FLD(instr, INSTR_I) == 0) - return IF_RD | IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2 | IF_W_RD; - else - return IF_RD | IF_RS1 | IF_W_RD | IF_R_RS1; - - case OP3_ADDC: - case OP3_SUBC: - if (RD_FLD(instr, INSTR_I) == 0) - return IF_RD| IF_RS1 | IF_RS2 | IF_RCC | IF_W_RD | IF_R_RS1 | IF_R_RS2; - else - return IF_RD| IF_RS1 | IF_RCC | IF_W_RD | IF_R_RS1; - - - - case OP3_XNORcc: - case OP3_ANDNcc: - case OP3_ANDcc: - case OP3_ADDcc: - case OP3_ORcc: - case OP3_ORNcc: - case OP3_SUBcc: - case OP3_XORcc: - if (RD_FLD(instr, INSTR_I) == 0) - return IF_RD | IF_RS1 | IF_RS2 | IF_WCC | IF_W_RD | IF_R_RS1 | IF_R_RS2; - else - return IF_RD | IF_RS1 | IF_WCC | IF_W_RD | IF_R_RS1; - - case OP3_ADDCcc: - case OP3_SUBCcc: - if (RD_FLD(instr, INSTR_I) == 0) - return IF_RD | IF_RS1 | IF_RS2 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1 | IF_R_RS2; - else - return IF_RD | IF_RS1 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1; - - case OP3_MOVcc: - if (RD_FLD(instr, INSTR_I) == 0) - { - if (RD_FLD(instr, INSTR_COND_L)==COND_BA) - return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2; - else - return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2 | IF_RCC; - } - else - { - if (RD_FLD(instr, INSTR_COND_L)==COND_BA) - return IF_RD | IF_W_RD; - else - return IF_RD | IF_W_RD | IF_RCC; - } - - default: - printf("Unknown:OP=0b10 OP3 = 0x%04X\n", RD_FLD(instr, INSTR_OP3)); - assert(0); - - } - return 0; + switch(RD_FLD(instr, INSTR_OP3)) + { + case OP3_DONERETRY: + assert(0); // This appears to be a system instruction + // either way though it acts like a branch + // and should NOT appear in an trace + return 0; + + case OP3_FCMP: + case OP3_FPU: + assert(0); // TODO: Add support when we do floating point + // support! + return 0; + + case OP3_FLUSHW: //OP=OP_2 I = 0 + return 0; // Flush has no negative side effects + + case OP3_FLUSH: //OP=OP_2 RS1 {I=0 -> IF_RS2, I=1->simm13} + if (RD_FLD(instr, INSTR_I) == 0) + return IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2; + else + return IF_RS1 | IF_R_RS1; + + case OP3_JMPL: //OP=OP_2 RD, IF_RS1 {I=0-> IF_RS2, I=1->SIMM13} + case OP3_ADD: + case OP3_AND: + case OP3_OR: + case OP3_XOR: + case OP3_SUB: + case OP3_ANDN: + case OP3_ORN: + case OP3_XNOR: + case OP3_MULX: + case OP3_SDIVX: + case OP3_UDIVX: + case OP3_SLL: + case OP3_SRL: + case OP3_SRA: + case OP3_SAVE: + case OP3_RETURN: + case OP3_RESTORE: + if (RD_FLD(instr, INSTR_I) == 0) + return IF_RD | IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2 | IF_W_RD; + else + return IF_RD | IF_RS1 | IF_W_RD | IF_R_RS1; + + case OP3_ADDC: + case OP3_SUBC: + if (RD_FLD(instr, INSTR_I) == 0) + return IF_RD| IF_RS1 | IF_RS2 | IF_RCC | IF_W_RD | IF_R_RS1 | IF_R_RS2; + else + return IF_RD| IF_RS1 | IF_RCC | IF_W_RD | IF_R_RS1; + + + + case OP3_XNORcc: + case OP3_ANDNcc: + case OP3_ANDcc: + case OP3_ADDcc: + case OP3_ORcc: + case OP3_ORNcc: + case OP3_SUBcc: + case OP3_XORcc: + if (RD_FLD(instr, INSTR_I) == 0) + return IF_RD | IF_RS1 | IF_RS2 | IF_WCC | IF_W_RD | IF_R_RS1 | IF_R_RS2; + else + return IF_RD | IF_RS1 | IF_WCC | IF_W_RD | IF_R_RS1; + + case OP3_ADDCcc: + case OP3_SUBCcc: + if (RD_FLD(instr, INSTR_I) == 0) + return IF_RD | IF_RS1 | IF_RS2 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1 | IF_R_RS2; + else + return IF_RD | IF_RS1 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1; + + case OP3_MOVcc: + if (RD_FLD(instr, INSTR_I) == 0) + { + if (RD_FLD(instr, INSTR_COND_L)==COND_BA) + return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2; + else + return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2 | IF_RCC; + } + else + { + if (RD_FLD(instr, INSTR_COND_L)==COND_BA) + return IF_RD | IF_W_RD; + else + return IF_RD | IF_W_RD | IF_RCC; + } + + default: + printf("Unknown:OP=0b10 OP3 = 0x%04X\n", RD_FLD(instr, INSTR_OP3)); + assert(0); + + } + return 0; } +//***************************************************************************** +// unsigned sparc_analyze3(unsigned instr) +// +// Analyze instructions with OP field set to OP_3 +// +//***************************************************************************** unsigned sparc_analyze3(unsigned instr) { - switch(RD_FLD(instr, INSTR_OP3)) - { - //OP=OP_3 RD, IF_RS1 {I=0->IF_RS2, I=1->SIMM13} - // BUG FIX! ST* does not write to RD, rather it reads!! - case OP3_STB: - case OP3_STH: - case OP3_STW: - case OP3_STX: - - if (RD_FLD(instr, INSTR_I) == 0) - return IF_RD | IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2 | IF_R_RD; - else - return IF_RD | IF_RS1 | IF_R_RS1 | IF_R_RS2 | IF_R_RD; - - case OP3_STFA: - case OP3_STDFA: - case OP3_STQFA: - assert(0); - return 0; - - case OP3_LDSB: - case OP3_LDSH: - case OP3_LDSW: - case OP3_LDUB: - case OP3_LDUH: - case OP3_LDUW: - case OP3_LDX: - case OP3_LDSTUB: - if (RD_FLD(instr, INSTR_I) == 0) - return IF_RD | IF_RS1 | IF_RS2 | IF_W_RD | IF_R_RS1 | IF_R_RS2; - else - return IF_RD | IF_RS1 | IF_W_RD | IF_R_RS1; - - - // compare and exchange r[rd] with value at r[rs1] depending on - // comparison between r[rs1] and r[rs2] - case OP3_CASXA: - case OP3_CASA: - return IF_RD | IF_RS1 | IF_RS2 | IF_W_RD | IF_R_RD | IF_RS1 | IF_RS2; - - // Cache line prefetch instructions - case OP3_PREFETCHA: - case OP3_PREFETCH: - if (RD_FLD(instr, INSTR_I) == 0) - return IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2; - else - return IF_RS1 | IF_R_RS1; - - default: - printf("Unknown OP_3: OP3 = %08X\n", RD_FLD(instr, INSTR_OP3)); - assert(0); - } - return 0; + switch(RD_FLD(instr, INSTR_OP3)) + { + //OP=OP_3 RD, IF_RS1 {I=0->IF_RS2, I=1->SIMM13} + // BUG FIX! ST* does not write to RD, rather it reads!! + case OP3_STB: + case OP3_STH: + case OP3_STW: + case OP3_STX: + + if (RD_FLD(instr, INSTR_I) == 0) + return IF_RD | IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2 | IF_R_RD; + else + return IF_RD | IF_RS1 | IF_R_RS1 | IF_R_RS2 | IF_R_RD; + + case OP3_STFA: + case OP3_STDFA: + case OP3_STQFA: + assert(0); + return 0; + + case OP3_LDSB: + case OP3_LDSH: + case OP3_LDSW: + case OP3_LDUB: + case OP3_LDUH: + case OP3_LDUW: + case OP3_LDX: + case OP3_LDSTUB: + if (RD_FLD(instr, INSTR_I) == 0) + return IF_RD | IF_RS1 | IF_RS2 | IF_W_RD | IF_R_RS1 | IF_R_RS2; + else + return IF_RD | IF_RS1 | IF_W_RD | IF_R_RS1; + + + // compare and exchange r[rd] with value at r[rs1] depending on + // comparison between r[rs1] and r[rs2] + case OP3_CASXA: + case OP3_CASA: + return IF_RD | IF_RS1 | IF_RS2 | IF_W_RD | IF_R_RD | IF_RS1 | IF_RS2; + + // Cache line prefetch instructions + case OP3_PREFETCHA: + case OP3_PREFETCH: + if (RD_FLD(instr, INSTR_I) == 0) + return IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2; + else + return IF_RS1 | IF_R_RS1; + + default: + printf("Unknown OP_3: OP3 = %08X\n", RD_FLD(instr, INSTR_OP3)); + assert(0); + } + return 0; } +//***************************************************************************** +// unsigned sparc_analyze_full(unsigned instr) +// +// Analyze general instructions. +// +//***************************************************************************** + unsigned sparc_analyze_full(unsigned instr) { - if (RD_FLD(instr,INSTR_OP)==OP_2) - return sparc_analyze_c2(instr); - else if (RD_FLD(instr,INSTR_OP)==OP_3) - return sparc_analyze3(instr); - else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH) - return sparc_analyzebr(instr); - else - return IF_CALL; // Call instruction not seen as branch - // in that control flow change is transparent - // to trace - return 0; + if (RD_FLD(instr,INSTR_OP)==OP_2) + return sparc_analyze_c2(instr); + else if (RD_FLD(instr,INSTR_OP)==OP_3) + return sparc_analyze3(instr); + else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH) + return sparc_analyzebr(instr); + else + return IF_CALL; // Call instruction not seen as branch + // in that control flow change is transparent + // to trace + return 0; } +//***************************************************************************** +// unsigned sparc_analyze(unsigned instr) +// +// Certain registers namely G0 (since writes don't take) +// must be ignored during dataflow analysis. Thus after +// running the full analysis pass we read all parameters +// that are marked as present - if the register is one of the +// banned ones we pretend that field isn't read. +// +//***************************************************************************** + unsigned sparc_analyze(unsigned instr) { - unsigned flags = sparc_analyze_full(instr); - - // validate that none of these registers are R0 if - // they are cancel read or write flags on that field - - if (flags & IF_RS1) - if ((1 << RD_FLD(instr, INSTR_RS1)) & RM_IGNORE) - flags &= ~IF_R_RS1; - if (flags & IF_RS2) - if ((1 << RD_FLD(instr, INSTR_RS2)) & RM_IGNORE) - flags &= ~IF_R_RS2; - - if (flags & IF_RD) - if ((1 << RD_FLD(instr, INSTR_RD)) & RM_IGNORE) - flags &= ~(IF_R_RD | IF_W_RD); + unsigned flags = sparc_analyze_full(instr); - return flags; + // validate that none of these registers are R0 if + // they are cancel read or write flags on that field + + if (flags & IF_RS1) + if ((1 << RD_FLD(instr, INSTR_RS1)) & RM_IGNORE) + flags &= ~IF_R_RS1; + if (flags & IF_RS2) + if ((1 << RD_FLD(instr, INSTR_RS2)) & RM_IGNORE) + flags &= ~IF_R_RS2; + + if (flags & IF_RD) + if ((1 << RD_FLD(instr, INSTR_RD)) & RM_IGNORE) + flags &= ~(IF_R_RD | IF_W_RD); + + return flags; } +//***************************************************************************** +// unsigned sparc_getwrites(unsigned mask, unsigned instr) +// +// Mask is the result from sparc_analyze. +// +// Returns a mask describing which registers were written to +// CC0 isn't in here. +// +//***************************************************************************** unsigned sparc_getwrites(unsigned mask, unsigned instr) { - if (mask & IF_RD) - return (1 << RD_FLD(instr, INSTR_RD)); - else - return 0; + if (mask & IF_W_RD) + return (1 << RD_FLD(instr, INSTR_RD)); + else + return 0; } +//***************************************************************************** +// unsigned sparc_getreads(unsigned mask, unsigned instr) +// +// Mask is the result from sparc_analyze. +// +// Returns a mask describing which registers were read from +// +//***************************************************************************** unsigned sparc_getreads (unsigned mask, unsigned instr) { - unsigned m = 0; - - if (mask & IF_RS1) - m |= (1 << RD_FLD(instr, INSTR_RS1)); + unsigned m = 0; + + if (mask & IF_R_RS1) + m |= (1 << RD_FLD(instr, INSTR_RS1)); - if (mask & IF_RS2) - m |= (1 << RD_FLD(instr, INSTR_RS2)); + if (mask & IF_R_RS2) + m |= (1 << RD_FLD(instr, INSTR_RS2)); + + if (mask & IF_R_RD) + m |= (1 << RD_FLD(instr, INSTR_RD)); - return m; + return m; } -unsigned sparc_getcc (unsigned mask, unsigned instr) // bit 0 -> CC READ , bit 1 -> CC write +//***************************************************************************** +// unsigned sparc_getcc(unsigned mask, unsigned instr) +// +// Mask is the result from sparc_analyze. +// +// Returns the part of the mask strictly dealing with WCC or RCC +// +//***************************************************************************** + +unsigned sparc_getcc (unsigned mask, unsigned instr) { - return (mask & (IF_WCC | IF_RCC)); + return (mask & (IF_WCC | IF_RCC)); } +//***************************************************************************** +// unsigned sparc_getbrdest(unsigned instr) +// +// Returns the relative offset for the branch (in instruction words) +// eg 1 means 1 instruction forward. // // Complete list of instructions that require relocation: // BPr -> D16LO/D16HI field @@ -292,54 +362,67 @@ // Bicc -> DISP22 field (deprecated) // BPcc -> DISP19 field // CALL -> DISP30 field - -// returns relative branch destination (in instruction words) +//***************************************************************************** + signed sparc_getbrdest(unsigned instr) { - if (RD_FLD(instr, INSTR_OP)==OP_CALL) - return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP30),30); - else - { - assert(RD_FLD(instr,INSTR_OP)==OP_BRANCH); - switch(RD_FLD(instr, INSTR_OP2)) - { - case OP2_BPR: // D16LO/D16HI - return SIGN_EXTEND(RD_D16(instr), 16); - case OP2_BICC: // DISP22 field - case OP2_FB: // DISP22 field - return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP22), 22); - case OP2_FBP: // DISP19 field - case OP2_BPICC: // DISP19 field - return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP19), 19); - default: - assert(0); - } - - } + if (RD_FLD(instr, INSTR_OP)==OP_CALL) + return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP30),30); + else + { + assert(RD_FLD(instr,INSTR_OP)==OP_BRANCH); + switch(RD_FLD(instr, INSTR_OP2)) + { + case OP2_BPR: // D16LO/D16HI + return SIGN_EXTEND(RD_D16(instr), 16); + case OP2_BICC: // DISP22 field + case OP2_FB: // DISP22 field + return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP22), 22); + case OP2_FBP: // DISP19 field + case OP2_BPICC: // DISP19 field + return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP19), 19); + default: + assert(0); + } + + } } +//***************************************************************************** +// unsigned sparc_setbrdest(unsigned instr, signed reladdr) +// +// Modifies the relative destination of a given branch +// +//***************************************************************************** + unsigned sparc_setbrdest(unsigned instr, signed reladdr) { - - if (RD_FLD(instr,INSTR_OP)==OP_CALL) - return MK_FLD(INSTR_OP, OP_CALL) | MK_FLD(INSTR_DISP30, unsigned(reladdr) & 0x3FFFFFFF); - else - { - assert(RD_FLD(instr,INSTR_OP)==OP_BRANCH); - switch(RD_FLD(instr, INSTR_OP2)) - { - case OP2_BPR: // D16LO/D16HI - return RM_FLD(INSTR_D16LO, RM_FLD(INSTR_D16HI, instr)) | MK_FLD(INSTR_D16LO, unsigned(reladdr) & 0x3FFF) | MK_FLD(INSTR_D16HI, (unsigned(reladdr) >> 14) & 3); - - case OP2_BICC: // DISP22 field - case OP2_FB: // DISP22 field - return RM_FLD(INSTR_DISP22, instr) | MK_FLD(INSTR_DISP22, unsigned(reladdr) & 0x003FFFFF); - case OP2_FBP: // DISP19 field - case OP2_BPICC: // DISP19 field - return RM_FLD(INSTR_DISP19, instr) | MK_FLD(INSTR_DISP19, unsigned(reladdr) & 0x0007FFFF); - default: - assert(0); - } - } + + if (RD_FLD(instr,INSTR_OP)==OP_CALL) + return MK_FLD(INSTR_OP, OP_CALL) | + MK_FLD(INSTR_DISP30, unsigned(reladdr) & 0x3FFFFFFF); + else + { + assert(RD_FLD(instr,INSTR_OP)==OP_BRANCH); + + switch(RD_FLD(instr, INSTR_OP2)) + { + case OP2_BPR: // D16LO/D16HI + return RM_FLD(INSTR_D16LO, RM_FLD(INSTR_D16HI, instr)) | + MK_FLD(INSTR_D16LO, unsigned(reladdr) & 0x3FFF) | + MK_FLD(INSTR_D16HI, (unsigned(reladdr) >> 14) & 3); + + case OP2_BICC: // DISP22 field + case OP2_FB: // DISP22 field + return RM_FLD(INSTR_DISP22, instr) | + MK_FLD(INSTR_DISP22, unsigned(reladdr) & 0x003FFFFF); + case OP2_FBP: // DISP19 field + case OP2_BPICC: // DISP19 field + return RM_FLD(INSTR_DISP19, instr) | + MK_FLD(INSTR_DISP19, unsigned(reladdr) & 0x0007FFFF); + default: + assert(0); + } + } } Index: llvm/lib/Reoptimizer/BinInterface/analyze.h diff -u llvm/lib/Reoptimizer/BinInterface/analyze.h:1.4 llvm/lib/Reoptimizer/BinInterface/analyze.h:1.5 --- llvm/lib/Reoptimizer/BinInterface/analyze.h:1.4 Sat Dec 14 19:31:33 2002 +++ llvm/lib/Reoptimizer/BinInterface/analyze.h Sun Dec 15 05:07:01 2002 @@ -1,5 +1,5 @@ //***************************************************************************** -// SPARC Instruction Analysis +// SPARC Instruction Analysis // // Analysis API Header // @@ -27,8 +27,8 @@ #define IF_R_RS2 0x200 // reads from RS2 #define IF_CALL 0x400 // Is call instruction? (affects live registers) #define IF_USR 0x800 // Later in the code we wish to be able to pack other - // flags along side these when we store them in the - // SSA form. This is the first 'user' flag available +// flags along side these when we store them in the +// SSA form. This is the first 'user' flag available Index: llvm/lib/Reoptimizer/BinInterface/bitmath.h diff -u llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.4 llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.5 --- llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.4 Sat Dec 14 19:31:33 2002 +++ llvm/lib/Reoptimizer/BinInterface/bitmath.h Sun Dec 15 05:07:01 2002 @@ -18,7 +18,7 @@ #ifndef __BITMATH_H__ #define __BITMATH_H__ - + //********************************* // Misc functions //********************************* @@ -26,7 +26,7 @@ #define ROUNDUP_P2(x, k) ((x+P2KM1(k)) &~ P2KM1(k)) #define ROUNDUP32(x) ROUNDUP_P2(x,5) // round up to nearest mult of 32 - + //********************************* // Bitfield manipulation Macros //********************************* @@ -44,7 +44,7 @@ //********************************** #define SIGN_EXTEND13(x) (x & 0x1000 ? -(-x & 0x1FFF): x) #define SIGN_EXTEND(x, bits) (x & (1 << (bits-1)) ? -(-x & ((1 << bits)-1)):x) - + #define IS_POWER_2(x) !(x & (x-1)) #define LOWEST_BIT(x) (x & ~(x & (x-1))) #define UPPER_BITS(x) (x & (x-1)) @@ -52,84 +52,84 @@ // Good if expected number of bits set < 4 static int countbits_sparse(unsigned m) //VALIDATED { - int c = 0; - while (m) - { - c++; - m = UPPER_BITS(m); - } - return c; + int c = 0; + while (m) + { + c++; + m = UPPER_BITS(m); + } + return c; } // base 2 sum of digits (hardwired for 32-bit) static int countbits_dense(unsigned w) //VALIDATED { - w = (0x55555555 & w) + (0x55555555 & (w >> 1)); - w = (0x33333333 & w) + (0x33333333 & (w >> 2)); - w = (w + (w>>4)) & 0x0f0f0f0f; - w = w + (w>>16); - w = w + (w>>8); - return w&0xFF; + w = (0x55555555 & w) + (0x55555555 & (w >> 1)); + w = (0x33333333 & w) + (0x33333333 & (w >> 2)); + w = (w + (w>>4)) & 0x0f0f0f0f; + w = w + (w>>16); + w = w + (w>>8); + return w&0xFF; } static bool ismod3(unsigned w) //VALIDATED { - w = (w >> 16) + (w&0xFFFF); - w = (w >> 8) + (w&0xFF); - w = (w >> 4) + (w&0xF); - w = (w >> 2) + (w&0x3); - return (0xB6DB6DB6 >> w) & 1; + w = (w >> 16) + (w&0xFFFF); + w = (w >> 8) + (w&0xFF); + w = (w >> 4) + (w&0xF); + w = (w >> 2) + (w&0x3); + return (0xB6DB6DB6 >> w) & 1; } static int mod3(unsigned w) //VALIDATED { - w = (w >> 16) + (w&0xFFFF); - w = (w >> 8) + (w&0xFF); - w = (w >> 4) + (w&0xF); - w = (w >> 2) + (w&0x3); - //use lookuptable - return (0x24924924 >> (w<<1)) & 3; + w = (w >> 16) + (w&0xFFFF); + w = (w >> 8) + (w&0xFF); + w = (w >> 4) + (w&0xF); + w = (w >> 2) + (w&0x3); + //use lookuptable + return (0x24924924 >> (w<<1)) & 3; } static int parity(unsigned w) //VALIDATED { - w ^= w >> 16; - w ^= w >> 8; - w ^= w >> 4; - w ^= w >> 2; - w ^= w >> 1; - return w & 1; + w ^= w >> 16; + w ^= w >> 8; + w ^= w >> 4; + w ^= w >> 2; + w ^= w >> 1; + return w & 1; } // // Note: users of this function may depend on the fact -// that log2(0) will return 0. Since it is +// that log2(0) will return 0. Since it is // undefined I have chosen this value. // -static int log2(unsigned w) //VALIDATED +static int log2_bits32(unsigned w) //VALIDATED { - int n = 0; + int n = 0; - if (w >> 16) - { - w >>= 16; - n+=16; - } - if (w >> 8) - { - w >>= 8; - n+=8; - } - if (w >> 4) - { - w >>= 4; - n+=4; - } + if (w >> 16) + { + w >>= 16; + n+=16; + } + if (w >> 8) + { + w >>= 8; + n+=8; + } + if (w >> 4) + { + w >>= 4; + n+=4; + } - w <<= 1; - return ((0xFFFFAA50 >> w) & 3)+n; // this is a LUT + w <<= 1; + return ((0xFFFFAA50 >> w) & 3)+n; // this is a LUT } Index: llvm/lib/Reoptimizer/BinInterface/construct.cpp diff -u llvm/lib/Reoptimizer/BinInterface/construct.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/construct.cpp:1.2 --- llvm/lib/Reoptimizer/BinInterface/construct.cpp:1.1 Sat Dec 14 19:31:37 2002 +++ llvm/lib/Reoptimizer/BinInterface/construct.cpp Sun Dec 15 05:07:11 2002 @@ -1,6 +1,6 @@ //***************************************************************************** // SPARC Binary Manipulation Interface -// +// // SSA Construction // // Interface Definition @@ -13,226 +13,274 @@ #include #include "salloc.h" // Stack allocator class #include "fvector.h" // fast vector (sits on stack allocator) -#include "analyze.h" // SPARC analysis library (gets flag masks for instrs) +#include "analyze.h" // SPARC analysis library #include "sparcbin.h" // Prototype for this class -#include "sparcpriv.h" // Private definitions#include "machine.h" // machine constants for cache optimizations +#include "sparcpriv.h" // Private definitions #include "sparcdis.h" // prototype for sparc disassembler #include "bitmath.h" // header of optimized binary math routines -#include "sparc9.h" // SPARC 9 opcode definitions +#include "sparc9.h" // SPARC 9 opcode definitions +#include "regmask.h" // the register mask allocator + #include +using std::pair; // use STL pair class -using std::pair; #include -#include "regmask.h" +//***************************************************************************** +// process_markgen(unsigned s, unsigned map[32], +// fvector & regmaps) +// +// Second pass +// +// unsigned s - the section id to process +// map[kreg] - the SSA id that is represented by reg 'kreg' +// at section entry/exit. This routine +// is responsible for replacing this with +// the register state at the end of section. +// +// Any instructions that read from a register that has an SSA id of 0 +// is assumed to be live-in. +// +// The instructions will get their genrs1/genrs2/genrd fields expanded +// in this fucntion +// +//***************************************************************************** +void BinInterface::process_markgen (unsigned s, unsigned map[32]) +{ + // iterate all instructions in this section + for (int i = begin(s); i!=end(s); ) + { + // look at instruction + instruction * instr = itable[i]; + unsigned flags = instr->flags; + // what uses? + if (flags & IF_R_RS1) + { + int rs1 = RD_FLD(instr->instr, INSTR_RS1); + if (!map[rs1]) + // oops. we just made a reference to an incoming value. Instantiate + map[rs1] = allocnodelivein(sections[0],rs1); -void BinInterface::process_markgen(unsigned s, unsigned map[32],fvector & regmaps) -{ - // iterate all instructions in this section - for (int i = begin(s); i!=end(s); ) - { - // look at instruction - instruction * instr = itable[i]; - unsigned flags = instr->flags; - - // what uses? - if (flags & IF_R_RS1) - { - int rs1 = RD_FLD(instr->instr, INSTR_RS1); - if (!map[rs1]) - // oops. we just made a reference to an incoming value. Instantiate - map[rs1] = allocnodelivein(sections[0],rs1); - - instr->alu.genrs1 = map[rs1]; - } - - if (flags & IF_R_RS2) - { - int rs2 = RD_FLD(instr->instr, INSTR_RS2); - if (!map[rs2]) - map[rs2] = allocnodelivein(sections[0],rs2); - instr->alu.genrs2 = map[rs2]; - } - - if (flags & IF_R_RD) - { - int rd = RD_FLD(instr->instr, INSTR_RD); - if (!map[rd]) - map[rd] = allocnodelivein(sections[0], rd); - instr->alu.genrd = map[rd]; - } - - // does he write to a register? - if (flags & IF_W_RD) - map[RD_FLD(instr->instr, INSTR_RD)] = i; - else if (flags & IF_PHI) - map[instr->instr] = instr->self; // use phi node for reg val - - // advance - i = instr->next; - - } + instr->alu.genrs1 = map[rs1]; + } + + if (flags & IF_R_RS2) + { + int rs2 = RD_FLD(instr->instr, INSTR_RS2); + if (!map[rs2]) + map[rs2] = allocnodelivein(sections[0],rs2); + instr->alu.genrs2 = map[rs2]; + } + + if (flags & IF_R_RD) + { + int rd = RD_FLD(instr->instr, INSTR_RD); + if (!map[rd]) + map[rd] = allocnodelivein(sections[0], rd); + instr->alu.genrd = map[rd]; + } + + // does he write to a register? + if (flags & IF_W_RD) + map[RD_FLD(instr->instr, INSTR_RD)] = i; + else if (flags & IF_PHI) + map[instr->instr] = instr->self; // use phi node for reg val + + // advance + i = instr->next; + + } } +//***************************************************************************** +// construct_merge(int s, int brdest, unsigned map[32], +// fvector & regmaps) +// +// +// +//***************************************************************************** -void BinInterface::process_section(unsigned s, unsigned map[32],fvector & regmaps) +void BinInterface::construct_merge(int s, int brdest, unsigned map[32], fvector & regmaps) { - // We inherit map from parent (p->t->e) -- FIX HANDLING OF MULTIPLE EPILOGS - for (int v=0;v<32;v++) - regmaps[s][v] = map[v]; - - // iterate all instructions in this section - for (int i = begin(s); i!=end(s); ) + // Iterate across all registers + for (int q=0;q<32;q++) + if (!regmaps[brdest][q]) // section we branched to + // had no data on register q + regmaps[brdest][q] = map[q]; // inherit the value + // using the SSA contents at our + // point + + else if (regmaps[brdest][q]!=map[q]) // not the same? { - // look at instruction - instruction * instr = itable[i]; - unsigned flags = instr->flags; + // we need a phi node - or we need to append to one + instruction * d = itable[regmaps[brdest][q]]; + if (d->flags & IF_PHI) + { + // nothing is in the register on our side + if (!map[q]) + map[q] = allocnodelivein(s,q); //must have been livein - // is the instruction a branch? - if (flags & IF_BRINTERNAL) + d->phi.params->push_back(map[q]); // append to a phi node + } + else // There wasn't already a PHI node { - - // follow the branch and MERGE the tables. - int brdest = instr->ibranch.dest; - - for (int q=0;q<32;q++) - if (!regmaps[brdest][q]) - regmaps[brdest][q] = map[q]; - else if (regmaps[brdest][q]!=map[q]) - { - // we need a phi node - or we need to append to one - instruction * d = itable[regmaps[brdest][q]]; - if (d->flags & IF_PHI) - { - if (!map[q]) - map[q] = allocnodelivein(s,q); //must have been livein - d->phi.params->push_back(map[q]); // append to a phi node - } - else - { - // create a phi node - instruction * phi = allocphi(); - - // Live in check - if (!regmaps[brdest][q]) - regmaps[brdest][q] = allocnodelivein(s,q); - - phi->phi.params->push_back(regmaps[brdest][q]); - - // live in check - if (!map[q]) - map[q] = allocnodelivein(s,q); - - phi->phi.params->push_back(map[q]); - - // link in the phi node and update both maps - insert_instr(sections[s], phi); - map[q] = phi->self; - regmaps[brdest][q] = phi->self; - phi->instr = q; // the register it applies to - } - } - + // create a phi node + instruction * phi = allocphi(); + + // Live in check + if (!regmaps[brdest][q]) + regmaps[brdest][q] = allocnodelivein(s,q); + + phi->phi.params->push_back(regmaps[brdest][q]); + + // live in check + if (!map[q]) + map[q] = allocnodelivein(s,q); + + phi->phi.params->push_back(map[q]); + + // link in the phi node and update both maps + insert_instr(sections[s], phi); + map[q] = phi->self; + regmaps[brdest][q] = phi->self; + phi->instr = q; // the register it applies to } - - // does he write to a register? - if (flags & IF_W_RD) - map[RD_FLD(instr->instr, INSTR_RD)] = i; - - i = instr->next; - } + } +} + +//***************************************************************************** +// process_section(unsigned s, unsigned map[32], +// fvector & regmaps) +// unsigned s - the section to process +// map[reg] - this routine fills this structure with the SSA +// contents AFTER exiting the section +// regmaps[s][r] - the SSA contents at the top of section 's' in reg 'r' +// +//***************************************************************************** + + +void BinInterface::process_section(unsigned s, unsigned map[32], + fvector & regmaps) +{ + // Inherit + for (int v=0;v<32;v++) + regmaps[s][v] = map[v]; + + // iterate all instructions in this section + for (int i = begin(s); i!=end(s); ) + { + // look at instruction + instruction * instr = itable[i]; + unsigned flags = instr->flags; + + // is the instruction a branch? + if (flags & IF_BRINTERNAL) + { + + // follow the branch and MERGE the tables. + int brdest = instr->ibranch.dest; + construct_merge( s, brdest, map, regmaps); + + } + + // does he write to a register? + if (flags & IF_W_RD) + map[RD_FLD(instr->instr, INSTR_RD)] = i; + + i = instr->next; + } } - + +//***************************************************************************** +// reduce() +// +// Must be called after complete(). Reduces the original binary code +// into SSA form +// +//***************************************************************************** void BinInterface::reduce() { - fvector regmaps(alloca); + fvector regmaps(alloca); + regmaps.resize(sections.size()); + + unsigned map[32]; + + // Initially all registers have unknown SSA values + for (int i = 0; i < 32; i++) + map[i] = 0; + + // Clear header maps + for (int s=0;sinstr holds the register number in question - // - // Execute program in order and connect phi nodes - // - - // clear the map - for (int v=0;v<32;v++) - map[v] = 0; - - process_markgen(SECTION_PROLOG, map, regmaps); - process_markgen(SECTION_TRACE , map, regmaps); - - - for (int s=SECTION_TRACE+1;s * shuffles = new fvector(alloca); - shuffles->sizehint(16); - - - for (i=0;i<32; i++) - { - instruction * instr = itable[mapepi[i]]; - if (instr->flags & IF_PHI) - { - // if any of the PHI parameters are marked live out, - // the phi node itself becomes liveout. - unsigned flags; - for (int s = 0; s< instr->phi.params->size(); s++) - flags |= itable[(*instr->phi.params)[s]]->flags; - if (flags & IF_LIVEOUT) - { - shuffles->push_back(shufflepair(i,mapepi[i])); - } - } - if (itable[mapepi[i]]->flags & IF_LIVEOUT) - { - // this one is liveout. Let's do the insertion - int mi = mapepi[i]; - shuffles->push_back(shufflepair(i,mapepi[i])); - } - } - // place the shuffler node - allocnodeshuffles(s, shuffles); - } + // Calculate phi nodes and contents of registers + // at section start points + process_section(SECTION_PROLOG, map, regmaps); + process_section(SECTION_TRACE, map, regmaps); + + // there is am implicit transition from TRACE->first epilog + construct_merge(SECTION_TRACE, SECTION_TRACE+1, map, regmaps); + + + + // clear the map + for (int v=0;v<32;v++) + map[v] = 0; + + // Update gen fields for instructions (can't be done + // in last pass due to insertion of PHI's) + process_markgen(SECTION_PROLOG, map); + process_markgen(SECTION_TRACE , map); + + // For each epilog + for (int s=SECTION_TRACE+1;s * shuffles = new fvector(alloca); + + shuffles->sizehint(16); + + for (i=1;i<32; i++) + { + unsigned ssaid = regmaps[s][i]; + + if (!ssaid) + continue; + + instruction * instr = itable[ssaid]; + if (instr->flags & IF_PHI) + { + // if any of the PHI parameters are marked live out, + // the phi node itself becomes liveout. + unsigned flags = 0; + + for (int s = 0; s< instr->phi.params->size(); s++) + flags |= itable[(*instr->phi.params)[s]]->flags; + + if (flags & IF_LIVEOUT) + shuffles->push_back(shufflepair(i,ssaid)); + } + if (itable[ssaid]->flags & IF_LIVEOUT) + { + // this one is liveout. Let's do the insertion + shuffles->push_back(shufflepair(i,ssaid)); + } + } + // place the shuffler node + allocnodeshuffles(s, shuffles); + } } Index: llvm/lib/Reoptimizer/BinInterface/emit.cpp diff -u llvm/lib/Reoptimizer/BinInterface/emit.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/emit.cpp:1.2 --- llvm/lib/Reoptimizer/BinInterface/emit.cpp:1.1 Sat Dec 14 19:31:37 2002 +++ llvm/lib/Reoptimizer/BinInterface/emit.cpp Sun Dec 15 05:07:16 2002 @@ -1,6 +1,6 @@ //***************************************************************************** // SPARC Binary Manipulation Interface -// +// // Code Emitter // // Interface Definition @@ -13,326 +13,383 @@ #include #include "salloc.h" // Stack allocator class #include "fvector.h" // fast vector (sits on stack allocator) -#include "analyze.h" // SPARC analysis library (gets flag masks for instrs) +#include "analyze.h" // SPARC analysis library #include "sparcbin.h" // Prototype for this class -#include "sparcpriv.h" // Private definitions#include "machine.h" // machine constants for cache optimizations +#include "sparcpriv.h" // Private definitions #include "sparcdis.h" // prototype for sparc disassembler #include "bitmath.h" // header of optimized binary math routines -#include "sparc9.h" // SPARC 9 opcode definitions -#include +#include "sparc9.h" // SPARC 9 opcode definitions +#include "regmask.h" // Register mask allocator +#include // Use STL pair class using std::pair; -#include -#include "regmask.h" +#include +//***************************************************************************** +// prepare_exit(regalloc & regalloc, +// fvector * mod, +// unsigned * & out) +// +// For liveout nodes this generates the series of instructions +// needed to get the SSA values in 'mod' into their correct registers. +// This is used during liveout transitions. +// +//***************************************************************************** -void BinInterface::prepare_exit(const regalloc & regalloc, fvector * mod, unsigned * & out) +void BinInterface::prepare_exit(const regalloc & regalloc, + fvector * mod, + unsigned * & out) { - fvector orig_reg(alloca); // what register is the value for each mod pair in - fvector regs(alloca); // what 'mod' pair is in a given register - int spillidx=0; - - orig_reg.sizehint((*mod).size()); - regs.resize(32); - for (int k = 0; k<32;k++) - regs[k] = 0; - - // lookup the registers each gen-site is in - for (int k = 0; k<(*mod).size();k++) - { - int vr = regalloc.ssa_to_vreg[(*mod)[k].gen]; - int mr = regalloc.vregs[vr].mreg; - orig_reg.push_back(regalloc.vregs[vr].mreg); - - if (mr < 32) // in a machine register? - regs[mr] = k; - } - - // load each one-by-one spilling registers as needed - for (int k=0; k<(*mod).size(); k++) - { - int dreg = (*mod)[k].reg; - int sreg = orig_reg[k]; - - if (sreg==dreg) - continue; - - // is that register free? if not spill it - if (regs[dreg]) - { - // spill whats in DREG to an unused register or memory location? - unsigned spillm = regalloc.memspills[spillidx++]; - *out++=MK_STX_STACK(dreg, (spillm-32)*8); - } - - // do move - if (sreg > 32) - *out++=MK_LDX_STACK(dreg, (sreg-32)*8); - else - { - regs[sreg] = 0; - *out++=MK_MOV_R_R(dreg, sreg); - } - - - } - + // what register is the value for each mod pair in + fvector orig_reg(alloca); + + // what 'mod' pair is in a given register + fvector regs(alloca); + + int spillidx=0; // index into regalloc.memspills + // (memspills is a set of Stack + // locations that are safe to use) + + orig_reg.sizehint((*mod).size()); + regs.resize(32); + + for (int k = 0; k<32;k++) + regs[k] = 0; + + // lookup the registers each gen-site is in + for (int k = 0; k<(*mod).size();k++) + { + int vr = regalloc.ssa_to_vreg[(*mod)[k].gen]; + int mr = regalloc.vregs[vr].mreg; + orig_reg.push_back(regalloc.vregs[vr].mreg); + + if (VREG_ISREG(mr)) // in a machine register? + regs[mr] = k; + } + + // load each one-by-one spilling registers as needed + for (int k=0; k<(*mod).size(); k++) + { + int dreg = (*mod)[k].reg; + int sreg = orig_reg[k]; + + if (sreg==dreg) + continue; + + // is that register free? if not spill it + if (regs[dreg]) + { + // spill whats in DREG to an unused register or memory location? + unsigned spillm = regalloc.memspills[spillidx++]; + *out++=MK_STX_STACK(dreg, VREG_GETMEM(spillm)); + } + + // do move + if (VREG_ISMEM(sreg)) + *out++=MK_LDX_STACK(dreg, VREG_GETMEM(sreg)); + else + { + regs[sreg] = 0; + *out++=MK_MOV_R_R(dreg, sreg); + } + } } -int BinInterface::spill_load(int vreg, regmask32 & rmask, const int memspills[32],int & freereg, int spilled[32], int & spilled_cnt, unsigned * & out) + +//***************************************************************************** +// prepare_exit(int vreg, regmask32 & rmask, +// const int memspills[32],int & freereg, +// int spilled[32], int & spilled_cnt, +// unsigned * & out) +// +// spilled/spilled_cnt - the registers that were spilled (max of 3) +// and must be reloaded +// memspills - locations available for memory spilling +// (there are 32) but we use the one corresponding +// to the register we're spilling +// freereg - register that's been reserved and is free +// for spill-loads. This will be set to 0 +// when it is consumed +// vreg - the value we want in memory +// rmask - a mask containing 'available' candidates for spill +// we need this so we don't double spill the same reg +// +// For liveout nodes this generates the series of instructions +// needed to get the SSA values in 'mod' into their correct registers. +// This is used during liveout transitions. +// +//***************************************************************************** +int BinInterface::spill_load(int vreg, regmask32 & rmask, + const int memspills[32],int & freereg, + int spilled[32], int & spilled_cnt, + unsigned * & out) { - assert(vreg >= 32); // doesn't make sense if it is ALREADY a register + assert(VREG_ISMEM(vreg)); // doesn't make sense if it is ALREADY a register + + int r = 0; + // can we used the set-aside register? + if (freereg) + { + r = freereg; + freereg = 0; + } + else + { // no? grab one from spill_candidates + r=rmask.allocreg(); + assert(r); + + // spill the value in that register out to memory + spilled[spilled_cnt] = r; + *out++=MK_STX_STACK(r, VREG_GETMEM(memspills[spilled_cnt])); + spilled_cnt++; + } + // now load the value from memory + *out++=MK_LDX_STACK(r, VREG_GETMEM(vreg)); - int r = 0; - // can we used the set-aside register? - if (freereg) - { - r = freereg; - freereg = 0; - } - else - { // no? grab one from spill_candidates - r=rmask.allocreg(); - assert(r); - - // spill the value in that register out to memory - spilled[spilled_cnt] = r; - *out++=MK_STX_STACK(r, 8*(memspills[spilled_cnt] - 32)); - spilled_cnt++; - } - // now load the value from memory - *out++=MK_LDX_STACK(r, 8*(vreg-32)); - - return r; + return r; } +//***************************************************************************** +// emit_gen(unsigned char * cde, const regalloc & regs) +// +// cde - the buffer to receive the code (sized using predict() ) +// regs - the result from register selection +// +//***************************************************************************** unsigned BinInterface::emit_gen(unsigned char * cde, const regalloc & regs) { - int s; - unsigned * out = (unsigned *) cde; + int s; + unsigned * out = (unsigned *) cde; - const fvector & ssa_to_vreg = regs.ssa_to_vreg; - const fvector & vregs = regs.vregs; - const int & spillreg = regs.spillreg; - const unsigned & touched_regs = regs.touched_regs; - const unsigned & liveout_regs = regs.liveout_regs; - - - fvector > fwdbranch(alloca); // pairs of instruction addrs +destination section #'s - fvector secaddr(alloca); // address of section - - regmask32 rmask; - secaddr.inc(sections.size()); - - unsigned stack_size = regs.stack_size; - - // calculate the set of registers we must save and alloc stack - unsigned save_regs = regs.touched_regs & ~ regs.liveout_regs; - unsigned save_area = stack_size; - stack_size += countbits_dense(save_regs)*8; - - // allocate space at top of prolog - *out++=MK_ADD_R_I(R_SP, R_SP, -stack_size); - - // save the registers - for (unsigned m=save_regs, l = 0, a=save_area; l<32;l++, m>>=1) - if (m & 1) - { - *out++=MK_STX_STACK(l, a); - a+=8; - } - - // Iterate across instructions - for (s=0;sflags; - - if (flags & (IF_REGSHUFFLE | IF_NODELIVEIN)) + // pairs of instruction addrs +destination section #'s + // (used for branch resolution) + fvector > fwdbranch(alloca); + + // address of section when emitted + fvector secaddr(alloca); + + // mask to be used for spill candidates + regmask32 rmask; + + secaddr.inc(sections.size()); + + // load stack size from allocator + unsigned stack_size = regs.stack_size; + + // calculate the set of registers we must save and alloc stack + // and allocate space for them in the prolog (and save) + unsigned save_regs = regs.touched_regs & ~ regs.liveout_regs; + unsigned save_area = stack_size; + stack_size += countbits_dense(save_regs)*8; + *out++=MK_ADD_R_I(R_SP, R_SP, -stack_size); + + for (unsigned m=save_regs, l = 0, a=save_area; l<32;l++, m>>=1) + if (m & 1) + { + *out++=MK_STX_STACK(l, a); + a+=8; + } + + // Iterate across instructions + for (s=0;sflags; + + if (flags & (IF_REGSHUFFLE | IF_NODELIVEIN)) + { + if (flags & IF_REGSHUFFLE) { - if (flags & IF_REGSHUFFLE) - { - prepare_exit(regs, instr->regshuffle.shuffles,out); - - } - else // nodelivein - { - int id = ssa_to_vreg[i]; - int dreg = vregs[id].mreg; - int sreg = instr->livein.reg; - - if (dreg!=sreg) - { - if (dreg < 32) - *out++=MK_MOV_R_R(dreg, sreg); - else - *out++=MK_STX_STACK(sreg, (dreg-32)*8); - } - } - continue; + prepare_exit(regs, instr->regshuffle.shuffles,out); + } - - // make sure this is ACTUALLY an instruction and not a phi node - if (! (flags & (IF_ALUOP | IF_BR))) - continue; - - // Find out what registers the instruction is already using (since the values - // were assigned to registers by defaults - rmask.set(R_ALLOCREGS); - - if (flags & IF_R_RS1) - { - rs1 = vregs[ssa_to_vreg[instr->alu.genrs1]].mreg; - - if (rs1 < 32) - rmask.grabreg(rs1); - } - if (flags & IF_R_RS2) - { - rs2 = vregs[ssa_to_vreg[instr->alu.genrs2]].mreg; - - if (rs2 < 32) - rmask.grabreg(rs2); - } - if (flags & IF_R_RD) - { - r_rd = vregs[ssa_to_vreg[instr->alu.genrd]].mreg; - - if (r_rd < 32) - rmask.grabreg(r_rd); - } - - - int freereg = spillreg; // the free spill register - this gets zerod when used - int spilled[3]; // array containing the registers that were spilled - // spilled[k] ALWAYS spills to memspills[k] - int spilled_cnt = 0; // how many registers were spilled - - unsigned ins = instr->instr; - - - // load parameters of instruction and spill as needed - if (flags & IF_R_RS1) - { - if (rs1 >= 32) - rs1 = spill_load(rs1, rmask, regs.memspills, freereg, spilled, spilled_cnt, out); - ins = RM_FLD(INSTR_RS1, ins) | MK_FLD(INSTR_RS1, rs1); - } - - if (flags & IF_R_RS2) + else // nodelivein { - if (rs2 >= 32) - rs2 = spill_load(rs2, rmask, regs.memspills, freereg, spilled, spilled_cnt, out); - ins = RM_FLD(INSTR_RS2, ins) | MK_FLD(INSTR_RS2, rs2); - } - - if (flags & IF_R_RD) + int id = regs.ssa_to_vreg[i]; + int dreg = regs.vregs[id].mreg; + int sreg = instr->livein.reg; + + if (dreg!=sreg) + { + if (VREG_ISREG(dreg)) + *out++=MK_MOV_R_R(dreg, sreg); + else + *out++=MK_STX_STACK(sreg, VREG_GETMEM(dreg)); + } + } + continue; + } + + // make sure this is ACTUALLY an instruction and not a phi node + if (! (flags & (IF_ALUOP | IF_BR))) + continue; + + // Find out what registers the instruction is already using + // (since the values were assigned to registers by defaults + rmask.set(R_ALLOCREGS); + + if (flags & IF_R_RS1) + { + rs1 = regs.vregs[regs.ssa_to_vreg[instr->alu.genrs1]].mreg; + + if (VREG_ISREG(rs1)) + rmask.grabreg(rs1); + } + if (flags & IF_R_RS2) + { + rs2 = regs.vregs[regs.ssa_to_vreg[instr->alu.genrs2]].mreg; + + if (VREG_ISREG(rs2)) + rmask.grabreg(rs2); + } + if (flags & IF_R_RD) + { + r_rd = regs.vregs[regs.ssa_to_vreg[instr->alu.genrd]].mreg; + + if (VREG_ISREG(r_rd)) + rmask.grabreg(r_rd); + } + + // the free spill register - this gets zerod when used + int freereg = regs.spillreg; + + // array containing the registers that were spilled + // NOTE: spilled[k] ALWAYS spills to memspills[k] + int spilled[3]; + int spilled_cnt = 0; // how many registers are in spilled + + unsigned ins = instr->instr; + + // load parameters of instruction and spill as needed + if (flags & IF_R_RS1) + { + if (VREG_ISMEM(rs1)) + rs1 = spill_load(rs1, rmask, regs.memspills, + freereg, spilled, spilled_cnt, out); + + ins = RM_FLD(INSTR_RS1, ins) | MK_FLD(INSTR_RS1, rs1); + } + + if (flags & IF_R_RS2) + { + if (VREG_ISMEM(rs2)) + rs2 = spill_load(rs2, rmask, regs.memspills, + freereg, spilled, spilled_cnt, out); + + ins = RM_FLD(INSTR_RS2, ins) | MK_FLD(INSTR_RS2, rs2); + } + + if (flags & IF_R_RD) + { + if (VREG_ISMEM(r_rd)) + r_rd = spill_load(r_rd, rmask, regs.memspills, + freereg, spilled, spilled_cnt, out); + + ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, r_rd); + } + // + // Branch instructions must have their target fixed up + // (note that the next instruction emitted is guaranteed + // to be the actual instruction and not a spill fixup) + if (flags & IF_BR) + { + if (flags & IF_BRINTERNAL) { - if (r_rd >= 32) - r_rd = spill_load(r_rd, rmask, regs.memspills, freereg, spilled, spilled_cnt, out); - ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, r_rd); - } - // - // Branch instructions must have their target fixed up - // (note that the next instruction emitted is guaranteed - // to be the actual instruction and not a spill fixup) - if (flags & IF_BR) + // we need to fix up destination. + // forward branches we store a backtable FIXME + if (instr->ibranch.dest <= s) + { + unsigned rel = secaddr[instr->ibranch.dest] - out; + instr->instr = sparc_setbrdest(instr->instr,rel); + } + else + fwdbranch.push_back( + pair(out, instr->ibranch.dest)); + } + else { - if (flags & IF_BRINTERNAL) - { - // we need to fix up destination. If this is a backward branch no problem - // forward branches we store a backtable FIXME - if (instr->ibranch.dest <= s) - { - unsigned rel = secaddr[instr->ibranch.dest] - out; - instr->instr = sparc_setbrdest(instr->instr,rel); - } - else - fwdbranch.push_back(pair(out, instr->ibranch.dest)); - } - else - { - // do absolute jump - unsigned rel = instr->ebranch.dest - out; - instr->instr = sparc_setbrdest(instr->instr,rel); - } + // do absolute jump + unsigned rel = instr->ebranch.dest - out; + instr->instr = sparc_setbrdest(instr->instr,rel); } + } + + if (flags & IF_W_RD) + { + int id = regs.ssa_to_vreg[i]; + + // We need to generate and store a result. We should check to see + // if any registers are currently 'free'. If not we must spill one. - if (flags & IF_W_RD) - { - int id = ssa_to_vreg[i]; - - // We need to generate and store a result. We should check to see - // if any registers are currently 'free'. If not we must spill one. - - int dreg = vregs[id].mreg; - - if (dreg < 32) - { - ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, dreg); - *out++=ins; - } - else - { - // always use the spillreg since it contains - // a value that was loaded from memory that is - // a SECOND copy. - ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, spillreg); - *out++=ins; - *out++=MK_STX_STACK(spillreg, 8*(dreg - 32)); - } - } + int dreg = regs.vregs[id].mreg; + + if (VREG_ISREG(dreg)) + { + ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, dreg); + *out++=ins; + } else - *out++=(ins); // no dreg? just emit it - - // now unspill everything - for (int z=0;z SECTION_TRACE) // epilog sections + { + // free space at top of prolog + // restore registers + for (unsigned m=save_regs, l = 0, a=save_area; l<32;l++, m>>=1) + if (m & 1) + { + *out++=MK_LDX_STACK(l, a); + a+=8; } - } - - // - // End of section handler - // - if (s > 1) // epilog sections - { - // free space at top of prolog - // restore registers - for (unsigned m=save_regs, l = 0, a=save_area; l<32;l++, m>>=1) - if (m & 1) - { - *out++=MK_LDX_STACK(l, a); - a+=8; - } - *out++=MK_ADD_R_I(R_SP, R_SP, stack_size); - } - } - - // - // Handle forward branches. - // - for(int t = 0; t & i = fwdbranch[t]; - - unsigned rel = secaddr[i.second] - out; - *i.first = sparc_setbrdest(*i.first,rel); - } - - return out- ((unsigned *)cde); + // free stack space + *out++=MK_ADD_R_I(R_SP, R_SP, stack_size); + } + } + + // + // Handle forward branches. + // + for(int t = 0; t & i = fwdbranch[t]; + + unsigned rel = secaddr[i.second] - out; + *i.first = sparc_setbrdest(*i.first,rel); + } + + return out- ((unsigned *)cde); } Index: llvm/lib/Reoptimizer/BinInterface/fvector.h diff -u llvm/lib/Reoptimizer/BinInterface/fvector.h:1.5 llvm/lib/Reoptimizer/BinInterface/fvector.h:1.6 --- llvm/lib/Reoptimizer/BinInterface/fvector.h:1.5 Sat Dec 14 20:04:27 2002 +++ llvm/lib/Reoptimizer/BinInterface/fvector.h Sun Dec 15 05:07:18 2002 @@ -3,7 +3,7 @@ // // * Implementation of a vector class around // the stack allocator. Couldn't use STL -// because I need to support stored the +// because I need to support stored the // pointer to the allocator stack. // // 2002 Cameron Buschardt @@ -14,137 +14,138 @@ #include "salloc.h" #include +#include template class fvector { - T * v_begin; - T * v_end; - T * v_capacity; - Allocator * alloc; - - // make sure we have MEMORY up to that element - // does not construct those positions - void validate(T * pos) - { - assert(alloc); - if (pos < v_capacity) + T * v_begin; + T * v_end; + T * v_capacity; + Allocator * alloc; + + // make sure we have MEMORY up to that element + // does not construct those positions + void validate(T * pos) + { + assert(alloc); + if (pos < v_capacity) return; - unsigned ns = v_capacity - v_begin; - unsigned ms = pos - v_begin + 1; - if (!ns) + unsigned ns = v_capacity - v_begin; + unsigned ms = pos - v_begin + 1; + if (!ns) ns = 64; - else - while (ns < ms) - ns *= 2; - - T * n = (T *)alloc->resize(v_begin, sizeof(T) * ns); - v_end = (v_end - v_begin) + n; - v_capacity = n + ns; - v_begin = n; - - } - - fvector(const fvector &) {} - fvector & operator = (const fvector &) {} - void destroy(T * b, T * e) - { - while (b!=e) - { + else + while (ns < ms) + ns *= 2; + + T * n = (T *)alloc->resize(v_begin, sizeof(T) * ns); + v_end = (v_end - v_begin) + n; + v_capacity = n + ns; + v_begin = n; + + } + + fvector(const fvector &) {} + fvector & operator = (const fvector &) {} + void destroy(T * b, T * e) + { + while (b!=e) + { b->~T(); b++; - } - } - void construct(T * b, T * e) - { - while (b!=e) - { + } + } + void construct(T * b, T * e) + { + while (b!=e) + { new (b) T(); b++; - } - } -public: - typedef T * iterator; - - iterator begin() { return v_begin; } - iterator end() { return v_end; } - void clear() - { - assert(this); - destroy(v_begin, v_end); - if (v_begin) + } + } + public: + typedef T * iterator; + + iterator begin() { return v_begin; } + iterator end() { return v_end; } + void clear() + { + assert(this); + destroy(v_begin, v_end); + if (v_begin) alloc->free(v_begin); - v_begin = v_capacity = v_end = NULL; + v_begin = v_capacity = v_end = NULL; - } - unsigned size() - { - assert(this); - return v_end - v_begin; - } - - fvector(Allocator * a) - { - v_begin = v_end = v_capacity = NULL; - alloc = a; - } - - fvector() - { - v_begin = v_end = v_capacity = NULL; - alloc = NULL; - - } - - void setallocator(Allocator * a) - { - assert(!alloc); - alloc = a; - } - - void sizehint(unsigned v) - { - if (v_begin) + } + unsigned size() + { + assert(this); + return v_end - v_begin; + } + + fvector(Allocator * a) + { + v_begin = v_end = v_capacity = NULL; + alloc = a; + } + + fvector() + { + v_begin = v_end = v_capacity = NULL; + alloc = NULL; + + } + + void setallocator(Allocator * a) + { + assert(!alloc); + alloc = a; + } + + void sizehint(unsigned v) + { + if (v_begin) return; - v_begin = (T*)alloc->alloc(sizeof(T) * v); - v_end = v_begin; - v_capacity = v_begin + v; - } - - void push_back(const T & e) { - assert(this); - validate(v_end+1); - new (v_end) T(e); - v_end++; - } - - void inc(unsigned amt) // increase size by this amt - { - validate(v_end + amt); - construct(v_end, v_end+amt); - v_end += amt; - } - - void resize(unsigned amt) - { - if ((v_begin+amt) < v_end) - { + v_begin = (T*)alloc->alloc(sizeof(T) * v); + v_end = v_begin; + v_capacity = v_begin + v; + } + + void push_back(const T & e) { + assert(this); + validate(v_end); + new (v_end) T(e); + v_end++; + } + + void inc(unsigned amt) // increase size by this amt + { + validate(v_end + amt); + construct(v_end, v_end+amt); + v_end += amt; + } + + void resize(unsigned amt) + { + if ((v_begin+amt) < v_end) + { // got shorter destroy((v_begin+amt), v_end); - - } - else - { + + } + else + { // got longer validate( v_begin+amt); construct(v_end, v_begin+amt); - } - v_end = v_begin+amt; - } - T& operator[] (unsigned n) { - return v_begin[n]; } - const T & operator[] (unsigned n) const { return v_begin[n]; } + } + v_end = v_begin+amt; + } + T& operator[] (unsigned n) { + return v_begin[n]; } + const T & operator[] (unsigned n) const { return v_begin[n]; } }; Index: llvm/lib/Reoptimizer/BinInterface/regmask.h diff -u llvm/lib/Reoptimizer/BinInterface/regmask.h:1.1 llvm/lib/Reoptimizer/BinInterface/regmask.h:1.2 --- llvm/lib/Reoptimizer/BinInterface/regmask.h:1.1 Sat Dec 14 19:31:41 2002 +++ llvm/lib/Reoptimizer/BinInterface/regmask.h Sun Dec 15 05:07:22 2002 @@ -13,131 +13,135 @@ #include "bitmath.h" +#define VREG_ISMEM(x) (x >= 32) +#define VREG_ISREG(x) (x < 32) +#define VREG_GETMEM(x) ((x-32) * 8) + class regmask32 { -private: - unsigned freemap; + private: + unsigned freemap; -public: + public: - // Construct freemap, initially mark everyone free - regmask32() - : freemap(~0) - { - } - - // returns 0 on failure - unsigned allocreg() - { - unsigned mask = LOWEST_BIT(freemap); // on fail this will be 0 - freemap &= ~mask; // on fail this will be a nop - return log2(mask); // log2(0) == log2(1) == 0 (in this implementation!) - // I fully realize log2(0) is undefined - // mathematically - } - - // free a register - void freereg(unsigned idx) - { - freemap |= 1 << (idx & 31); // mark it free - } - - // force the register 'in-use' - void grabreg(unsigned idx) - { - freemap &= ~(1 << (idx & 31)); // grab it - } - - void set(unsigned mask) - { - freemap = mask; - } - - // count how many are free in the lowest 32. - unsigned count() - { - return countbits_dense(freemap); - } - - // get the mask of free registers - unsigned free() - { - return freemap; - } + // Construct freemap, initially mark everyone free + regmask32() + : freemap(~0) + { + } + + // returns 0 on failure + unsigned allocreg() + { + unsigned mask = LOWEST_BIT(freemap); // on fail this will be 0 + freemap &= ~mask; // on fail this will be a nop + return log2_bits32(mask); // log2(0) == log2(1) == 0 (in this implementation!) + // I fully realize log2(0) is undefined + // mathematically + } + + // free a register + void freereg(unsigned idx) + { + freemap |= 1 << (idx & 31); // mark it free + } + + // force the register 'in-use' + void grabreg(unsigned idx) + { + freemap &= ~(1 << (idx & 31)); // grab it + } + + void set(unsigned mask) + { + freemap = mask; + } + + // count how many are free in the lowest 32. + unsigned count() + { + return countbits_dense(freemap); + } + + // get the mask of free registers + unsigned free() + { + return freemap; + } }; class regmask { -private: - fvector freemap; + private: + fvector freemap; - unsigned i_allocreg(int baseindex) - { - for (;baseindex> 5 ); - for (int k = 0; k < freemap.size(); k++) - freemap[k].set(~0); - } - - // returns 0 on failure - unsigned allocreg() - { - return i_allocreg(0); // alloc physical or memory - } - - unsigned allocmemreg() - { - return i_allocreg(1); // force memory - } - - // returns 0 on failure - unsigned allocreg32() // allocate register from first 32 only - { - return freemap[0].allocreg(); - } - - void freereg(unsigned idx) - { - freemap[idx >> 5].freereg(idx & 31); - } - - void grabreg(unsigned idx) - { - freemap[idx >> 5].grabreg(idx & 31); // grab it - } - - void set32(unsigned mask) - { - freemap[0].set(mask); - } - - // count how many are free in the lowest 32. - unsigned count32() - { - return freemap[0].count(); - } - - unsigned free32() - { - return freemap[0].free(); - } + public: + // Construct freemap, initially mark everyone free + regmask(Allocator * a, unsigned maxregs) + : freemap(a) + { + // make sure maxregs is a multiple of 32 + assert(!(maxregs & 0x1F)); + + // calculate size of freemap + freemap.inc( maxregs >> 5 ); + for (int k = 0; k < freemap.size(); k++) + freemap[k].set(~0); + } + + // returns 0 on failure + unsigned allocreg() + { + return i_allocreg(0); // alloc physical or memory + } + + unsigned allocmemreg() + { + return i_allocreg(1); // force memory + } + + // returns 0 on failure + unsigned allocreg32() // allocate register from first 32 only + { + return freemap[0].allocreg(); + } + + void freereg(unsigned idx) + { + freemap[idx >> 5].freereg(idx & 31); + } + + void grabreg(unsigned idx) + { + freemap[idx >> 5].grabreg(idx & 31); // grab it + } + + void set32(unsigned mask) + { + freemap[0].set(mask); + } + + // count how many are free in the lowest 32. + unsigned count32() + { + return freemap[0].count(); + } + + unsigned free32() + { + return freemap[0].free(); + } }; #endif Index: llvm/lib/Reoptimizer/BinInterface/salloc.cpp diff -u llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.2 llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.3 --- llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.2 Sat Dec 14 19:31:41 2002 +++ llvm/lib/Reoptimizer/BinInterface/salloc.cpp Sun Dec 15 05:07:24 2002 @@ -1,7 +1,7 @@ //***************************************************************************** // Fast Stack Allocator // -// Implementation of Stack allocator +// Implementation of Stack allocator // // 2002 Cameron Buschardt //***************************************************************************** @@ -12,92 +12,169 @@ #include #include #include -// work around incompetant compiler -#define PRINTALLOC +// All allocation will be aligned to 16-byte boundaries +// if you change this DO NOT make it lower than 8 otherwise +// pointer types will not be sufficiently aligned and SPARC +// will throw an unaligned exception (as a bus error) +#define ALIGN 4 // align blocks to 2^4 bytes (16 bytes) // look up the size of a block by address -#define BSIZE(x) *((unsigned *)((unsigned char *)x - sizeof (unsigned))) +#define BSIZE(x) *(((unsigned *)x)-1) -void * StackAllocator::alloc(unsigned size) -{ - assert(top + size + sizeof(unsigned) <= end); - *((unsigned *)top) = size; - top+=sizeof(unsigned); +//***************************************************************************** +// adjust(size) +// +// rounds size up to the nearest multiple of 2^ALIGN +// +//***************************************************************************** - unsigned char * r= top; - top += size; +unsigned adjust(unsigned size) +{ + return ROUNDUP_P2(size, ALIGN); +} + +//***************************************************************************** +// alloc(unsigned size) +// +// Allocate a block size off the top of the stack +// note that an unsigned size field is stored RIGHT before the block +// +//***************************************************************************** - return r; +void * StackAllocator::alloc(unsigned size) +{ + unsigned fullsize = size+sizeof(unsigned); + fullsize = adjust(fullsize); + size = fullsize - sizeof(unsigned); + unsigned * sizeloc = (unsigned *)top; + unsigned char * block = (unsigned char *)(sizeloc+1); + unsigned char * eblock = top+fullsize; + assert(eblock <= end); + *sizeloc = size; + top = eblock; + return block; } + +//***************************************************************************** +// resize(void *block, unsigned size) +// +// Reallocate a block (in place if possible) +// +//***************************************************************************** + void * StackAllocator::resize(void * block , unsigned newsize) { - if (!block) - { - void * t = alloc(newsize); - PRINTALLOC("Resize(%08X, %d) = new block: %08X \n", block, newsize, t); - return t; - } - if ((BSIZE(block)+(unsigned char *)block)!=top) - { - unsigned char * r = (unsigned char *)alloc(newsize); - unsigned oldsize=BSIZE(block); - memcpy(r, block, oldsize); - PRINTALLOC("Resize(%08X, %d) = new block: %08X \n", block, newsize, r); - free(block); - return r; - } - else - { - // was the last alloc - unsigned oldsize = BSIZE(block); - assert(top + newsize - oldsize <= end); - BSIZE(block) = newsize; - top += newsize -oldsize; - PRINTALLOC("Resize(%08X, %d) = top resize: %08X \n", block, newsize, block); + if (!block) + return alloc(newsize); + if ((BSIZE(block)+(unsigned char *)block)!=top) // this block wasn't on top + { + unsigned char * r = (unsigned char *)alloc(newsize); + unsigned oldsize=BSIZE(block); + memcpy(r, block, oldsize); + this->free(block); + return r; + } + else + { + newsize=adjust(newsize+sizeof(unsigned))-sizeof(unsigned); + // was the last alloc + unsigned oldsize = BSIZE(block); + assert(top + newsize - oldsize <= end); + BSIZE(block) = newsize; + top += newsize -oldsize; - return block; - } + return block; + } } +//***************************************************************************** +// free(void * x) +// +// Perform a stack free - only removes memory if x is on the top of the stack +// otherwise we 'lose' that memory until the stack allocator is reset next +// +//***************************************************************************** + void StackAllocator::free(void * x) -{ - if (!x) - return; - - // NOT the top of the stack. cannot free - if ((BSIZE(x)+(unsigned char *)x)!=top) - { - PRINTALLOC("Free(%08X) ignored.\n", x); - return; - } - PRINTALLOC("Free(%08X) TOS.\n", x); - top = (unsigned char *)x; +{ + if (!x) + return; + + // NOT the top of the stack. cannot free + if ((BSIZE(x)+(unsigned char *)x)!=top) + return; + + top = (unsigned char *)x; } +//***************************************************************************** +// clear() +// +// Reset allocator +// +//***************************************************************************** + void StackAllocator::clear() { - top = begin; + top = begin; } + +//***************************************************************************** +// StackAllocator(unsigned heapsize) +// +// Allocates the heap using malloc and properly aligns everything. +// Assumes malloc is returning a block aligned at LEAST to 8 bytes +// (which should be true for SPARC64) +// +//***************************************************************************** + StackAllocator::StackAllocator(unsigned size) { - // round size up to next multiple of CACHE_LINE - size=ROUNDUP32(size); - begin = (unsigned char *)malloc(size); - end = begin + size; - top = begin; - } + // round size up to next multiple of CACHE_LINE + size =ROUNDUP32(size+(1 << ALIGN)); + begin = (unsigned char *)malloc(size); + end =begin + size; + begin+=((1<=begin && b<=top) + { + printf("\t%p: size=%d\n", b, BSIZE(b)); + b+=BSIZE(b)+sizeof(unsigned); + } } + Index: llvm/lib/Reoptimizer/BinInterface/salloc.h diff -u llvm/lib/Reoptimizer/BinInterface/salloc.h:1.3 llvm/lib/Reoptimizer/BinInterface/salloc.h:1.4 --- llvm/lib/Reoptimizer/BinInterface/salloc.h:1.3 Sat Dec 14 19:40:48 2002 +++ llvm/lib/Reoptimizer/BinInterface/salloc.h Sun Dec 15 05:07:29 2002 @@ -1,7 +1,7 @@ //***************************************************************************** // Fast Stack Allocator // -// Definitions of Base Allocator class and Stack allocator +// Definitions of Base Allocator class and Stack allocator // // // @@ -19,15 +19,31 @@ class Allocator { -public: - virtual void clear() = 0; - virtual void*alloc(unsigned size) = 0; - virtual void free(void * block) = 0; - virtual void*resize(void * block , unsigned newsize) = 0; - virtual ~Allocator() {} + public: + virtual void clear() = 0; + virtual void*alloc(unsigned size) = 0; + virtual void free(void * block) = 0; + virtual void*resize(void * block , unsigned newsize) = 0; + virtual ~Allocator() {} + virtual void print() = 0; }; +//********************************* +// C++ Allocator +//********************************* + +class CAllocator: public Allocator +{ + public: + virtual void clear() {} + virtual void*alloc(unsigned size) { return malloc(size); } + virtual void free(void * block) { ::free(block); } + virtual void*resize(void * block , unsigned size) { return ::realloc(block, size); } + virtual ~CAllocator() {} + virtual void print() {} +}; + //********************************* // Stack Allocator @@ -35,18 +51,18 @@ class StackAllocator : public Allocator { - unsigned char * begin; - unsigned char * end; - unsigned char * top; // current free - -public: - StackAllocator(unsigned size); - ~StackAllocator(); - void clear(); - void * alloc(unsigned size); - void * resize(void * block , unsigned newsize); - void free(void * block); - void print(); + unsigned char * begin; + unsigned char * end; + unsigned char * top; // current free + + public: + StackAllocator(unsigned size); + ~StackAllocator(); + void clear(); + void * alloc(unsigned size); + void * resize(void * block , unsigned newsize); + void free(void * block); + void print(); }; Index: llvm/lib/Reoptimizer/BinInterface/select.cpp diff -u llvm/lib/Reoptimizer/BinInterface/select.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/select.cpp:1.2 --- llvm/lib/Reoptimizer/BinInterface/select.cpp:1.1 Sat Dec 14 19:31:41 2002 +++ llvm/lib/Reoptimizer/BinInterface/select.cpp Sun Dec 15 05:07:29 2002 @@ -1,6 +1,6 @@ //***************************************************************************** // SPARC Binary Manipulation Interface -// +// // Register Allocator // // Interface Definition @@ -15,334 +15,297 @@ #include #include "salloc.h" // Stack allocator class #include "fvector.h" // fast vector (sits on stack allocator) -#include "analyze.h" // SPARC analysis library (gets flag masks for instrs) +#include "analyze.h" // SPARC analysis library #include "sparcbin.h" // Prototype for this class #include "sparcpriv.h" // Private definitions #include "sparcdis.h" // prototype for sparc disassembler #include "bitmath.h" // header of optimized binary math routines -#include "sparc9.h" // SPARC 9 opcode definitions -#include +#include "sparc9.h" // SPARC 9 opcode definitions +#include "regmask.h" // Register mask allocator +#include // Use STL pair class using std::pair; + #include -#include "regmask.h" +//***************************************************************************** +// select(regalloc & regs) +// +// Perform register allocation and store register assignments as well +// as memory heap requirements, spill areas, etc into regs structure +// +//***************************************************************************** void BinInterface::select(regalloc & regs) { - regs.touched_regs = 0; // mask containing all the touched registers - regs.liveout_regs = 0; - unsigned max_midx = 0; // max midx (32+stackelement) - int free_vreg = 1, s,k,i,p; // first free - - fvector & ssa_to_vreg = regs.ssa_to_vreg; - fvector & vregs = regs.vregs; - - - // Mark everyone as having no register assigned - ssa_to_vreg.inc(itable.size()); - for (k = 0; kflags; - - if (flags & IF_PHI) + regs.touched_regs = 0; // mask containing all the touched registers + regs.liveout_regs = 0; // mask of JUST liveout registers + + unsigned max_midx= 0; // maximal stack index that we access + + // don't assign vreg of 0. + int free_vreg = 1, s,k,i,p; // first free + + // This table stores the Virtual Registers that were + // assigned to each SSA node + fvector & ssa_to_vreg = regs.ssa_to_vreg; + + // This table has the live-range and register assignments + // for a given virtual register + fvector & vregs = regs.vregs; + + // Mark everyone as having no register assigned + ssa_to_vreg.inc(itable.size()); + for (k = 0; kflags; + + if (flags & IF_PHI) + { + for (int p=0; p< instr->phi.params->size(); p++) { - for (int p=0; p< instr->phi.params->size(); p++) - { - int id = (*instr->phi.params)[p]; - ssa_to_vreg[id] = free_vreg; - } - ssa_to_vreg[i] = free_vreg; - free_vreg++; + int id = (*instr->phi.params)[p]; + ssa_to_vreg[id] = free_vreg; } - } - - // size the vreg structures and initialize - vregs.inc(itable.size()); - for (p = 0 ; p < free_vreg; p++) - vregs[p].uses = vregs[p].lastuse = vregs[p].mreg = 0; - - - // Assign Vregs to non-phi parameters. Calculate usage information - // for ALL virtual registers. Also calculate liveout reg set - for (s=0;sflags; - - if (!ssa_to_vreg[i]) //not got a vreg yet? + ssa_to_vreg[i] = free_vreg; + free_vreg++; + } + } + + // size the vreg structures and initialize + vregs.inc(itable.size()); + for (p = 0 ; p < free_vreg; p++) + vregs[p].uses = vregs[p].lastuse = vregs[p].mreg = 0; + + // Assign Vregs to non-phi parameters. Calculate usage information + // for ALL virtual registers. Also calculate liveout reg set + for (s=0;sflags; + + if (!ssa_to_vreg[i]) //not got a vreg yet? + { + // allocate one + ssa_to_vreg[i] = free_vreg; + vregs.inc(1); + + vregs[free_vreg].uses = + vregs[free_vreg].lastuse = + vregs[free_vreg].mreg = 0; + + free_vreg++; + } + + if (flags & IF_REGSHUFFLE) + { + fvector * v = instr->regshuffle.shuffles; + for (int z=0;zsize();z++) { - // allocate one - ssa_to_vreg[i] = free_vreg; - vregs.inc(1); - vregs[free_vreg].uses = vregs[free_vreg].lastuse = vregs[free_vreg].mreg = 0; - free_vreg++; + int gen = (*v)[z].gen; + int vr = ssa_to_vreg[gen]; + vregs[vr].uses++; + vregs[vr].lastuse = i; + regs.liveout_regs |= (1 << (*v)[z].reg); //liveout reg } - - if (flags & IF_REGSHUFFLE) + continue; + } + + // note since PHI nodes have been collapsed + // through the vreg assignment. we don't need to process them! =p + // Livein nodes are also skipped + if (flags & (IF_ALUOP | IF_BR)) + { + if (flags & IF_R_RS1) // do we read from RS1? { - fvector * v = instr->regshuffle.shuffles; - for (int z=0;zsize();z++) - { - int gen = (*v)[z].gen; - int vr = ssa_to_vreg[gen]; - vregs[vr].uses++; - vregs[vr].lastuse = i; - regs.liveout_regs |= (1 << (*v)[z].reg); //liveout reg - } - continue; - } - - // note since PHI nodes have been collapsed - // through the vreg assignment. we don't need to process them! =p - // Livein nodes are also skipped - if (flags & (IF_ALUOP | IF_BR)) + int id = ssa_to_vreg[instr->alu.genrs1]; + vregs[id].uses++; + vregs[id].lastuse = i; + } + if (flags & IF_R_RS2) // do we read from RS2? { - if (flags & IF_R_RS1) // do we read from RS1? - { - int id = ssa_to_vreg[instr->alu.genrs1]; - vregs[id].uses++; - vregs[id].lastuse = i; - } - if (flags & IF_R_RS2) // do we read from RS2? - { - int id = ssa_to_vreg[instr->alu.genrs2]; - vregs[id].uses++; - vregs[id].lastuse = i; - } - if (flags & IF_R_RD) // do we read from RD? - { - int id = ssa_to_vreg[instr->alu.genrd]; - vregs[id].uses++; - vregs[id].lastuse = i; - } - } - } - - // register allocation state - regmask freeregs(alloca,ROUNDUP32(itable.size())+32); // includes stack positions - unsigned hwregs[32]; // vreg index in that register - freeregs.set32(R_ALLOCREGS); // mark candidate registers free - - for (s = 0; s< 32; s++) - hwregs[s] = 0; - - // Allocate registers that are marked as live in values - // note livein nodes are COPY instructions. - for (p = 0; plivein.reg; - vregs[ ssa_to_vreg[livein[p]] ].mreg = mreg; - - // Mark that register not free - freeregs.grabreg(mreg); - regs.touched_regs |= (1< max_midx) - max_midx = regs.memspills[z]; - } - - // Iterate across instructions - for (s=0;sflags; - - - // make sure this is ACTUALLY an instruction and not a phi node - if (! (flags & (IF_ALUOP | IF_BR))) - continue; - - unsigned ins = instr->instr; - // mask off and replace rs1 - if (flags & IF_R_RS1) - { - int vid = ssa_to_vreg[instr->alu.genrs1]; - if (vregs[vid].lastuse == i) - { - freeregs.freereg(vregs[vid].mreg); - - if (vregs[vid].mreg < 32) - hwregs[vregs[vid].mreg] = 0; - } - } - - if (flags & IF_R_RS2) - { - int vid = ssa_to_vreg[instr->alu.genrs2]; - if (vregs[vid].lastuse == i) - { - freeregs.freereg(vregs[vid].mreg); - if (vregs[vid].mreg < 32) - hwregs[vregs[vid].mreg] = 0; - } - } - - if (flags & IF_R_RD) - { - int vid = ssa_to_vreg[instr->alu.genrd]; - if (vregs[vid].lastuse == i) - { - freeregs.freereg(vregs[vid].mreg); - if (vregs[vid].mreg < 32) - hwregs[vregs[vid].mreg] = 0; - } - } - - if (flags & IF_W_RD) - { - int id = ssa_to_vreg[i]; - int dreg = freeregs.allocreg(); - - - if (dreg >= 32) - { - if (dreg > max_midx) - max_midx = dreg; - - // Select a live range to spill - unsigned min_cnt = 0xFFFFFFFF; - unsigned min_idx = 0; - - for (int j = 0; j < 32; j++) - { - if (!hwregs[j]) - continue; - - vreginfo & v = vregs[hwregs[j]]; - if (v.uses < min_cnt) - { - min_cnt = v.uses; - min_idx = j; - } - } - - // mincnt/minidx now contain the smallest allocated - - if (min_cnt < vregs[id].uses) - { - // spill using this register - int oid = hwregs[min_idx]; - vregs[id].mreg = min_idx; - assert(min_idx < 32); - hwregs[min_idx] = id; - - vregs[oid].mreg = dreg; - } - else - { - // no spill - vregs[id].mreg = dreg; - } - } - else - { - regs.touched_regs |= (1<alu.genrs2]; + vregs[id].uses++; + vregs[id].lastuse = i; + } + if (flags & IF_R_RD) // do we read from RD? { - int id = ssa_to_vreg[x]; - printf("l%d: -> v%d reg=%d\n", x,id, vregs[id].mreg); - }*/ - - // calculate amount of stack space needed - regs.stack_size = ((max_midx+1) - 32) * 8; -} + int id = ssa_to_vreg[instr->alu.genrd]; + vregs[id].uses++; + vregs[id].lastuse = i; + } + } + } -/* -// -// Spill load -// - loads value into register (performing spill if needed) -// - validates use constraints and identifies the end of a live-range -// -int BinInterface::spill_load(int useid, int id, unsigned * & out, fvector & vregs, regmask & freeregs, unsigned hwregs[32]) -{ - int rs1 = vregs[id].mreg; + // register allocation state - if (rs1 >= 32) // not a hardware register? - { - // First try allocating a candindate register - int sreg = freeregs.allocreg(); - - // if sreg wasn't a hardware register spill something into it - // and return the register we spilled - if (sreg >= 32) - sreg = spillreg(sreg, out, vregs, freeregs, hwregs); - - // update the virtual register map - hwregs[sreg] = id; - vregs[id].mreg = sreg; - freeregs.freereg(rs1); // free the old area since we're loading it - - // perform a spill load on the parameters - *out++=(MK_LDX_STACK(sreg, 8*(rs1-32))); - - - return sreg; - } - else - return rs1; //it was already in a register -} -int BinInterface::spillreg(int spillloc, unsigned * & out, fvector & vregs, regmask & freeregs, unsigned hwregs[32]) -{ + // + // We need potentially 1 spill for each SSA node + // as well as the 32 generic spill slots (used for + // shuffle instructions) + // + regmask freeregs(alloca,ROUNDUP32(itable.size())+32); - // Select a live range to spill - unsigned min_cnt = 0xFFFFFFFF; - unsigned min_idx = 0; - - for (int j = 0; j < 32; j++) - { - if (!hwregs[j]) + unsigned hwregs[32]; // vreg index in that register + freeregs.set32(R_ALLOCREGS); // mark candidate registers free + + for (s = 0; s< 32; s++) + hwregs[s] = 0; + + // Allocate registers that are marked as live in values + // note livein nodes are COPY instructions. + for (p = 0; plivein.reg; + vregs[ ssa_to_vreg[livein[p]] ].mreg = mreg; + + // Mark that register not free + freeregs.grabreg(mreg); + regs.touched_regs |= (1< max_midx) + max_midx = midx; + } + + // Iterate across instructions + for (s=0;sflags; + + + // make sure this is ACTUALLY an instruction and not a phi node + if (! (flags & (IF_ALUOP | IF_BR))) continue; - - vreginfo & v = vregs[hwregs[j]]; - if (v.uses < min_cnt) - { - min_cnt = v.uses; - min_idx = j; - } - } - // Spill the live range to the location we allocated - vregs[hwregs[min_idx]].mreg = spillloc; // update map - - // spill the live-range - *out++=(MK_STX_STACK(min_idx, 8*(spillloc - 32))); - - return min_idx; -} -*/ + unsigned ins = instr->instr; + // mask off and replace rs1 + if (flags & IF_R_RS1) + { + int vid = ssa_to_vreg[instr->alu.genrs1]; + if (vregs[vid].lastuse == i) + { + freeregs.freereg(vregs[vid].mreg); + if (VREG_ISREG(vregs[vid].mreg)) + hwregs[vregs[vid].mreg] = 0; + } + } + + if (flags & IF_R_RS2) + { + int vid = ssa_to_vreg[instr->alu.genrs2]; + if (vregs[vid].lastuse == i) + { + freeregs.freereg(vregs[vid].mreg); + if (VREG_ISREG(vregs[vid].mreg)) + hwregs[vregs[vid].mreg] = 0; + } + } + + if (flags & IF_R_RD) + { + int vid = ssa_to_vreg[instr->alu.genrd]; + if (vregs[vid].lastuse == i) + { + freeregs.freereg(vregs[vid].mreg); + if (VREG_ISREG(vregs[vid].mreg)) + hwregs[vregs[vid].mreg] = 0; + } + } + + if (flags & IF_W_RD) + { + int id = ssa_to_vreg[i]; + int dreg = freeregs.allocreg(); + + + if (VREG_ISMEM(dreg)) + { + unsigned midx = VREG_GETMEM(dreg); + + if (midx > max_midx) + max_midx = midx; + + // Select a live range to spill + unsigned min_cnt = 0xFFFFFFFF; + unsigned min_idx = 0; + + for (int j = 0; j < 32; j++) + { + if (!hwregs[j]) + continue; + + vreginfo & v = vregs[hwregs[j]]; + if (v.uses < min_cnt) + { + min_cnt = v.uses; + min_idx = j; + } + } + + // mincnt/minidx now contain the smallest allocated + + if (min_cnt < vregs[id].uses) + { + // spill using this register + int oid = hwregs[min_idx]; + vregs[id].mreg = min_idx; + + assert(min_idx < 32); + hwregs[min_idx] = id; + vregs[oid].mreg = dreg; + } + else + { + // no spill + vregs[id].mreg = dreg; + } + } + else + { + regs.touched_regs |= (1< v%d reg=%d\n", x,id, vregs[id].mreg); + }*/ + + // calculate amount of stack space needed + regs.stack_size = max_midx+8; +} Index: llvm/lib/Reoptimizer/BinInterface/sparc9.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.2 --- llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.1 Sat Dec 14 20:04:30 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparc9.cpp Sun Dec 15 05:07:33 2002 @@ -9,25 +9,28 @@ #include "sparc9.h" -char * cc_names[] = { "fcc0", "fcc1", "fcc2", "fcc3", "icc", "c101", "xcc", "c111"}; +char * cc_names[] = { "fcc0", "fcc1", "fcc2", "fcc3", + "icc", "c101", "xcc", "c111"}; //********************************** // Name Lookup tables // index is Condition code //********************************** -char * fcond_names[] = {"FBN","FBNE","FBLG","FBUL","FBL","FBUG","FBG","FBU","FBA","FBE", - "FBUE","FBGE","FBUGE","FBLE","FBULE","FBO"}; +char * fcond_names[] = {"FBN","FBNE","FBLG","FBUL","FBL","FBUG","FBG","FBU", + "FBA","FBE", "FBUE","FBGE","FBUGE","FBLE","FBULE", + "FBO"}; -char * icond_names[] = {"n","e","le","l","leu","cs","neg","vs","a","ne","g","ge", - "gu","cc","pos","vc"}; +char * icond_names[] = {"n","e","le","l","leu","cs","neg","vs","a","ne", + "g","ge","gu","cc","pos","vc"}; -char * rcond_names[] = {"r000", "RZ", "RLEZ", "r011", "r100", "RNZ", "RGZ", "RGEZ"}; +char * rcond_names[] = {"r000", "RZ", "RLEZ", "r011", "r100", "RNZ", "RGZ", + "RGEZ"}; char * reg_names[32] = { "G0", "G1", "G2", "G3", "G4", "G5", "G6", "G7", - "O0", "O1", "O2", "O3", "O4", "O5", "O6(SP)", "O7", - "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7", - "I0", "I1", "I2", "I3", "I4", "I5", "I6(FP)", "I7"}; + "O0", "O1", "O2", "O3", "O4", "O5", "O6(SP)", "O7", + "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7", + "I0", "I1", "I2", "I3", "I4", "I5", "I6(FP)", "I7"}; Index: llvm/lib/Reoptimizer/BinInterface/sparc9.h diff -u llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.7 llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.8 --- llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.7 Sat Dec 14 19:31:49 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparc9.h Sun Dec 15 05:07:33 2002 @@ -6,9 +6,9 @@ // 2002 Cameron Buschardt //***************************************************************************** -//********************************* +//***************************************************************************** // Register Names -//********************************* +//***************************************************************************** #define R_I7 31 #define R_I6 30 #define R_I5 29 @@ -50,9 +50,9 @@ extern char * reg_names[]; -//********************************** -// Instruction bitfield definitions -//********************************** +//***************************************************************************** +// Instruction bitfield definitions +//***************************************************************************** #define INSTR_OP 31:30 #define INSTR_A 29:29 #define INSTR_FCN 29:25 @@ -101,17 +101,17 @@ #define RD_D16(i) ((RD_FLD(i, INSTR_D16HI) << 14) | RD_FLD(i, INSTR_D16LO)) -//********************************** -// Op-code classification -//********************************** +//***************************************************************************** +// Op-code classification +//***************************************************************************** #define OP_CALL 0x00000001 /* 0b01 */ #define OP_BRANCH 0x00000000 /* 0b00 */ #define OP_2 0x00000002 /* 0b10 */ #define OP_3 0x00000003 /* 0b11 */ -//********************************** +//***************************************************************************** // Branch Class Instructions -//********************************** +//***************************************************************************** #define OP2_ILLTRAP 0x00000000 /* 0b000 */ //OP=OP_BRANCH #define OP2_NOP 0x00000004 /* 0b100 */ //BRANCH #define OP2_SETHI 0x00000004 /* 0b100 */ //BRANCH - uhh? duplicate? DOH =p @@ -121,18 +121,18 @@ #define OP2_FBP 0x00000005 /* 0b101 */ #define OP2_BPICC 0x00000001 /* 0b001 */ -//********************************** +//***************************************************************************** // Register Condition Codes -//********************************** +//***************************************************************************** #define RCOND_RZ 0x00000001 /* 0b001 */ #define RCOND_RLEZ 0x00000002 /* 0b010 */ #define RCOND_RNZ 0x00000005 /* 0b101 */ #define RCOND_RGZ 0x00000006 /* 0b110 */ #define RCOND_RGEZ 0x00000007 /* 0b111 */ -//********************************** +//***************************************************************************** // FPU Branch Conditions -//********************************** +//***************************************************************************** #define COND_FBN 0x00000000 /* 0b0000 */ #define COND_FBNE 0x00000001 /* 0b0001 */ #define COND_FBLG 0x00000002 /* 0b0010 */ @@ -150,9 +150,9 @@ #define COND_FBULE 0x0000000E /* 0b1110 */ #define COND_FBO 0x0000000F /* 0b1111 */ -//********************************** +//***************************************************************************** // Integer Branch Conditions -//********************************** +//***************************************************************************** #define COND_BN 0x00000000 /* 0b0000 */ #define COND_BE 0x00000001 /* 0b0001 */ #define COND_BLE 0x00000002 /* 0b0010 */ @@ -171,18 +171,18 @@ #define COND_BVC 0x0000000F /* 0b1111 */ -//********************************** +//***************************************************************************** // Name Lookup tables // index is Condition code -//********************************** +//***************************************************************************** extern char * fcond_names[]; extern char * icond_names[]; extern char * rcond_names[]; -//********************************** -// Flag register encoding -//********************************** +//***************************************************************************** +// Flag register encoding +//***************************************************************************** #define FLAG_FCC0 0x00000000 /* 0b000 */ #define FLAG_FCC1 0x00000001 /* 0b001 */ @@ -194,8 +194,8 @@ extern char * cc_names[]; -//********************************** -// OP_2 class instructions +//***************************************************************************** +// OP_2 class instructions // // present members: // RD, OP3, RS1 @@ -203,7 +203,7 @@ // RS2 // else // SIMM13 -//********************************** +//***************************************************************************** #define OP3_ADD 0x00000000 /* 0b000000 */ #define OP3_ADDC 0x00000008 /* 0b001000 */ @@ -363,9 +363,9 @@ MK_FLD(INSTR_RS1, R_SP) | \ MK_FLD(INSTR_I , 1 ) | \ MK_FLD(INSTR_SIMM13, stackoffs)) - -// Move a value between two registers + +// Move a value between two registers #define MK_MOV_R_R(dreg, sreg) \ (MK_FLD(INSTR_OP, OP_2) | \ MK_FLD(INSTR_RD, dreg) | \ @@ -376,7 +376,7 @@ MK_FLD(INSTR_CC2 , 1 ) | \ MK_FLD(INSTR_MOV_CC1 , 1 ) | \ MK_FLD(INSTR_MOV_CC0, 0 )) - + // Store a word in sreg to O6/SP + stackoffs #define MK_STX_STACK(sreg, stackoffs) \ (MK_FLD(INSTR_OP, OP_3) | \ @@ -385,7 +385,7 @@ MK_FLD(INSTR_RS1, R_SP) | \ MK_FLD(INSTR_I , 1 ) | \ MK_FLD(INSTR_SIMM13, stackoffs)) - + // Add a constant to a register #define MK_ADD_R_I(dreg, sreg, imm) \ (MK_FLD(INSTR_OP, OP_2) | \ Index: llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.2 llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.3 --- llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.2 Sat Dec 14 19:32:10 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp Sun Dec 15 05:07:37 2002 @@ -6,13 +6,13 @@ // Current flaws: // * Makes no attempts to handle the difficulties of call instructions // need to add 'affinity' for register allocator to handle efficient -// selection of Ixx registers. +// selection of Ixx registers. // * Needs to save parameter registers // // Goals // * Performance - Efficient use of memory and allocation code // * Minimal Algorithms- 100% linear time, and make as many assumptions -// based on our definition of trace as possible +// based on our definition of trace as possible // // 2002 Cameron Buschardt //***************************************************************************** @@ -21,360 +21,493 @@ #include #include "salloc.h" // Stack allocator class #include "fvector.h" // fast vector (sits on stack allocator) -#include "analyze.h" // SPARC analysis library (gets flag masks for instrs) +#include "analyze.h" // SPARC analysis library #include "sparcbin.h" // Prototype for this class -#include "sparcpriv.h" // Private definitions#include "machine.h" // machine constants for cache optimizations +#include "sparcpriv.h" // Private definitions #include "sparcdis.h" // prototype for sparc disassembler #include "bitmath.h" // header of optimized binary math routines -#include "sparc9.h" // SPARC 9 opcode definitions -#include +#include "sparc9.h" // SPARC 9 opcode definitions +#include // Bring in STL pair class using std::pair; -#include - -// 512kb initial size -#define BIN_INIT_HEAP_SIZE 0x80000 -#define MAX_SECTIONS 16 +#include #include - +//***************************************************************************** +// liveout(unsigned instr) // -// liveout: Marks an instruction liveout. Can only be called AFTER -// complete() and before reduce(). -// Only values marked liveout will be in the original/correct -// register by end of epilog! +// Marks an instruction liveout. Can only be called AFTER +// complete() and before reduce(). +// Only values marked liveout will be in the original/correct +// register by end of epilog! // +//***************************************************************************** void BinInterface::liveout(unsigned instr) { - itable[instr]->flags |= IF_LIVEOUT; + itable[instr]->flags |= IF_LIVEOUT; } +//***************************************************************************** +// emit(unsigned char * out) +// +// Do register selection and emit the code +// The user supplies the buffer +// (user knows "max" size through a call to predict) +// +//***************************************************************************** +unsigned BinInterface::emit(unsigned char * out) +{ + // + // This structure receives the register allocation + // and spill register information to be passed + // on to the emitter. + // + regalloc regs(alloca); + // Fill structure + select(regs); + // Compile code + return emit_gen(out, regs); +} - +//***************************************************************************** +// predict() // -// Perform a fast linear scan register allocation. -// * Dynamically allocates spill registers -// * Guarantees all parameters of a PHI node -// get mapped to the same register +// This function will correctly guess the largest size +// the buffer needs to be. // +//***************************************************************************** - - - -unsigned BinInterface::emit(unsigned char * out) +unsigned BinInterface::predict() { - int spillreg; - int memspills[32]; - unsigned touched, stack; - // Table to look up virtual register for SSA node - // this is done to condense PHI node references - regalloc regs(alloca); - - - select(regs); // condense phi nodes and calculate - // live ranges - - return emit_gen(out, regs); // do linear scan register allocation - // interleaved with code generation + return (4 * itable.size() + 32*4) * sizeof(unsigned); } +//***************************************************************************** +// allocphi() +// +// Allocate a PHI node from the user heap and link it in. +// +//***************************************************************************** +instruction * BinInterface::allocphi() +{ + instruction * phi = (instruction *)alloca->alloc(sizeof(instruction)); + phi->flags = IF_PHI; + phi->next = phi->prev = phi->self = itable.size(); + itable.push_back(phi); + // allocate memory for fvector AND call constructor + phi->phi.params = + (fvector *) alloca->alloc(sizeof(fvector)); + + new ((void *)phi->phi.params) fvector(alloca); + return phi; +} +//***************************************************************************** +// process_branch( +// +// brdest[section] - the original address of the first instruction +// in that section +// scns - number of sections +// insertion i - the queued insertion command, contains the list +// of instructions +// +// This function inserts the insertion into partial SSA instructions +// the only SSA fields that will be valid after this are the branch +// destinations +// +//***************************************************************************** - -unsigned BinInterface::predict() +void BinInterface::process_branch( + const insertion & i, unsigned ** brdest, int scns) { - return 16 * itable.size(); -} + unsigned cid = i.idstart; + unsigned *ibegin = i.begin; + unsigned *iend = i.end; + unsigned tail = sections[i.section]; -instruction * BinInterface::allocphi() -{ - instruction * phi = (instruction *)alloca->alloc(sizeof(instruction)); - - phi->flags = IF_PHI; - phi->next = phi->prev = phi->self = itable.size(); - itable.push_back(phi); - - // allocate memory for fvector AND call constructor - phi->phi.params = (fvector *)alloca->alloc(sizeof(fvector)); - new ((void *)phi->phi.params) fvector(alloca); + while(ibegin!=iend) + { + // Analyze the instruction + unsigned flags = sparc_analyze(*ibegin); - - return phi; -} + instruction * instr; -void BinInterface::process_branch(const insertion & i, unsigned ** brdest, int scns) -{ - unsigned cid = i.idstart; - unsigned *ibegin = i.begin; - unsigned *iend = i.end; - unsigned tail = sections[i.section]; + // Branch? + if (flags & IF_BR) + { + int fwd = sparc_getbrdest(*ibegin); // Relative adress + unsigned * dest = ibegin + fwd; // eval - - while(ibegin!=iend) - { - // look at the instruction - unsigned flags = sparc_analyze(*ibegin); - - instruction * instr; - - if (flags & IF_BR) - { - int fwd = sparc_getbrdest(*ibegin); - unsigned * dest = ibegin + fwd; + // allocate the SSA node + instr = (instruction *)alloca->alloc(sizeof(instruction)); - // create a branch instruction - instr = (instruction *)alloca->alloc(sizeof(instruction)); + instr->flags = flags; - instr->flags = flags; - // scan for branch destination - for (int l = 0; libranch.dest = l; - instr->flags |= IF_BRINTERNAL; - goto ibfound; - } + // found? this must be an internal + // branch! + instr->ibranch.dest = l; + instr->flags |= IF_BRINTERNAL; + goto ibfound; } - // must have been external - instr->ebranch.dest = dest; - - ibfound: // internal branch found - ; - - } - else - { - // create a generic ALU instruction - instr = (instruction *)alloca->alloc(sizeof(instruction)); - instr->flags = flags | IF_ALUOP; - instr->alu.genccf = instr->alu.genrs1 = instr->alu.genrs2 = 0; // zero reg - } - - instr->instr = *ibegin; - instr->self = cid; - - - itable[cid] = instr; - - insert_instr(tail, instr); - tail = cid; - - cid++; - ibegin++; - - } - + } + // must have been external (eg out of trace) + instr->ebranch.dest = dest; + +ibfound: // internal branch found + ; + + } + else + { + // create a generic ALU instruction since it wasn't + // a branch + instr = (instruction *)alloca->alloc(sizeof(instruction)); + instr->flags = flags | IF_ALUOP; + + // zero out SSA parameters + instr->alu.genccf = instr->alu.genrs1 = instr->alu.genrs2 = 0; + } + + // Store instruction data and store instruction ID # in + // the node + instr->instr = *ibegin; + instr->self = cid; + + // Add the instruction to the ID table + itable[cid] = instr; + + // Add instruction into linked list for given section + insert_instr(tail, instr); + tail = cid; + + cid++; + ibegin++; + + } + } +//***************************************************************************** +// complete() +// +// Since insertions into sections are queued (for branch resolution) +// this function is responsible for emptying the queues and inserting +// the instructions +// +//***************************************************************************** + void BinInterface::complete() { - int p; - assert(sections.size() <= MAX_SECTIONS); - // Compute branch destination table by section - unsigned * brdest[MAX_SECTIONS]; - - for (p = 0; pflags & IF_NODELIVEIN) - { - printf("l%04d: livein[r%d]\n", instr->self,instr->livein.reg); - } - else if (instr->flags & IF_REGSHUFFLE) - { - for (int k = 0; kregshuffle.shuffles->size(); k++) - printf("r%02d: liveout[l%04d]\n", (*instr->regshuffle.shuffles)[k].reg, (*instr->regshuffle.shuffles)[k].gen); - } - else if (instr->flags & IF_PHI) - { - printf("l%04d: phi[", instr->self); - for (int i=0;i<(*instr->phi.params).size();++i) - printf("%d ", (*instr->phi.params)[i]); - printf("]\n"); - } - else if (instr->flags & IF_BR) - { - printf("l%04d: ", instr->self); - if (instr->flags & IF_BRINTERNAL) - printf("{dest:s%02d} ", instr->ibranch.dest); - else - printf("{dest:0x%08X} ", instr->ebranch.dest); - - sparc_print_pseudo(instr->instr, instr->alu.genrs1, instr->alu.genrs2, -1, instr->alu.genccf); - printf("\n"); - - } - else - { - printf("l%04d: ", instr->self); - sparc_print_pseudo(instr->instr, instr->alu.genrs1, instr->alu.genrs2, -1, instr->alu.genccf); - printf("\n"); - } + while (u!=end(section)) + { + instruction * instr = itable[u]; + + if (instr->flags & IF_NODELIVEIN) + { + printf("l%04d: livein[r%d]\n", instr->self,instr->livein.reg); + } + else if (instr->flags & IF_REGSHUFFLE) + { + for (int k = 0; kregshuffle.shuffles->size(); k++) + printf("r%02d: liveout[l%04d]\n", + (*instr->regshuffle.shuffles)[k].reg, + (*instr->regshuffle.shuffles)[k].gen); + } + else if (instr->flags & IF_PHI) + { + printf("l%04d: phi[", instr->self); + for (int i=0;i<(*instr->phi.params).size();++i) + printf("%d ", (*instr->phi.params)[i]); + printf("]\n"); + } + else if (instr->flags & IF_BR) + { + printf("l%04d: ", instr->self); + if (instr->flags & IF_BRINTERNAL) + printf("{dest:s%02d} ", instr->ibranch.dest); + else + printf("{dest:0x%08X} ", instr->ebranch.dest); + + sparc_print_pseudo(instr->instr, + instr->alu.genrs1, + instr->alu.genrs2, + -1, + instr->alu.genccf); + printf("\n"); + + } + else + { + printf("l%04d: ", instr->self); + + sparc_print_pseudo(instr->instr, + instr->alu.genrs1, + instr->alu.genrs2, + -1, + instr->alu.genccf); + printf("\n"); + } - u = instr->next; - } + u = instr->next; + } } +//***************************************************************************** +// print() +// +// Prints all sections in SSA form +// +//***************************************************************************** + void BinInterface::print() { - //alloca->print(); + alloca->print(); - for (int p = 0; p< sections.size(); p++) - { - printf("Section %d\n",p); - print(p); - } + for (int p = 0; p< sections.size(); p++) + { + printf("Section %d\n",p); + print(p); + } } +//***************************************************************************** +// newepilog() +// +// Allocates a new epilog node and returns the instruction ID +// +//***************************************************************************** unsigned BinInterface::newepilog() { - unsigned v = sections.size(); - push_section(); - return v; + unsigned v = sections.size(); + push_section(); + return v; } +//***************************************************************************** +// insert_instr(unsigned instr_id, instruction *instr) +// +// Links instr into the linked list of instruction AFTER instr_id. +// instr->self must have been previously initialized +// +//***************************************************************************** void BinInterface::insert_instr(unsigned instr_id, instruction * instr) { - unsigned a = instr_id; - unsigned c = itable[a]->next; - - itable[a]->next = instr->self; - instr->prev = a; - - instr->next = c; - itable[c]->prev = instr->self; + unsigned a = instr_id; + unsigned c = itable[a]->next; + + itable[a]->next = instr->self; + instr->prev = a; + + instr->next = c; + itable[c]->prev = instr->self; } +//***************************************************************************** +// push_section() // -// AFTER AFTER->NEXT -// +// Adds a new section. Initialized empty. // -// AFTER INSTR AFTER->NEXT -void BinInterface::push_section() +//***************************************************************************** +void BinInterface::push_section() { - // create header node - instruction * instr = (instruction *)alloca->alloc(sizeof(instruction)); - instr->next = itable.size(); - instr->prev = itable.size(); - instr->flags = 0; - instr->self = itable.size(); - sections.push_back(itable.size()); - itable.push_back(instr); + // create header node + instruction * instr = (instruction *)alloca->alloc(sizeof(instruction)); + instr->next = itable.size(); + instr->prev = itable.size(); + instr->flags = 0; + instr->self = itable.size(); + sections.push_back(itable.size()); + itable.push_back(instr); } +//***************************************************************************** +// BinInterface(unsigned heapsize) +// +// Heapsize must be sufficiently large or memory allocations will fail! +// +// +//***************************************************************************** -BinInterface::BinInterface(unsigned instr_count) +BinInterface::BinInterface(unsigned heapsize) { - alloca = new StackAllocator(BIN_INIT_HEAP_SIZE + instr_count*16); - itable.setallocator(alloca); - sections.setallocator(alloca); - queue.setallocator(alloca); - livein.setallocator(alloca); - // create prolog and trace link nodes - push_section(); - push_section(); + alloca = new StackAllocator(heapsize); + itable.setallocator(alloca); + sections.setallocator(alloca); + queue.setallocator(alloca); + livein.setallocator(alloca); + // create prolog and trace link nodes + push_section(); + push_section(); } +//***************************************************************************** +// allocnodelivein(int s, int reg) +// +// Allocates a livein node and links it into the start of section 's'. +// the node is livein for given register. Instruction ID Is returned +// +//***************************************************************************** + unsigned BinInterface::allocnodelivein(int s, int reg) { - int idx = itable.size(); - instruction * instr = (instruction *)alloca->alloc(sizeof(instruction)); - instr->flags = IF_NODELIVEIN; - instr->livein.reg = reg; - instr->self = idx; - itable.push_back(instr); - livein.push_back(idx); - insert_instr(sections[s], instr); - return idx; - + int idx = itable.size(); + instruction * instr = (instruction *)alloca->alloc(sizeof(instruction)); + instr->flags = IF_NODELIVEIN; + instr->livein.reg = reg; + instr->self = idx; + itable.push_back(instr); + livein.push_back(idx); + insert_instr(sections[s], instr); + return idx; + } +//***************************************************************************** +// allocnodeshuffles(int s, fvector * shuffles) +// +// Allocates a shuffle node and links it into the start of section 's'. +// The shuffle node arranges for a set of SSA values to be in specific +// registers (used for liveout). Shuffles is a list of pairs of +// registers/instruction IDs. +// +//***************************************************************************** + unsigned BinInterface::allocnodeshuffles(int s, fvector * shuffles) { - int idx = itable.size(); - instruction * instr = (instruction *)alloca->alloc(sizeof(instruction)); - instr->flags = IF_REGSHUFFLE; - instr->regshuffle.shuffles = shuffles; - - instr->self = idx; - itable.push_back(instr); - insert_instr(end(s), instr); - return idx; + int idx = itable.size(); + instruction * instr = (instruction *)alloca->alloc(sizeof(instruction)); + instr->flags = IF_REGSHUFFLE; + instr->regshuffle.shuffles = shuffles; + + instr->self = idx; + itable.push_back(instr); + insert_instr(end(s), instr); + return idx; } +//***************************************************************************** +// insert(unsigned section, unsigned *ibegin, unsigned *iend) +// +// Queues an contiguous series of instructions for insertion upon +// completion of the complete() function +// +// NOTE: just like iterations iend is the first address NOT to insert. +// +//***************************************************************************** -unsigned BinInterface::insert(unsigned section, unsigned *ibegin, unsigned * iend) { - insertion i; - i.begin = ibegin; - i.end = iend; - i.section = section; - i.idstart = itable.size(); +unsigned BinInterface::insert(unsigned section, + unsigned *ibegin, unsigned * iend) +{ + // you're not allowed to have machine instructions + // INITIALLY in the epilogs + assert(section==SECTION_TRACE || section==SECTION_PROLOG); + + insertion i; + i.begin = ibegin; + i.end = iend; + i.section = section; + i.idstart = itable.size(); - itable.inc(iend - ibegin); - queue.push_back(i); + itable.inc(iend - ibegin); + queue.push_back(i); - return i.idstart; + return i.idstart; } +//***************************************************************************** +// clear() +// +// Reset the state of the binary interface so that we may compile a new +// trace (Very fast) +// +//***************************************************************************** + void BinInterface::clear() { - itable.clear(); - sections.clear(); - queue.clear(); - livein.clear(); - alloca->clear(); - // create prolog and trace link nodes - push_section(); - push_section(); + itable.clear(); + sections.clear(); + queue.clear(); + livein.clear(); + alloca->clear(); + // create prolog and trace link nodes + push_section(); + push_section(); } +//***************************************************************************** +// ~BinInterface() +// +// The only memory that we don't manage in our allocator is the heap block +// itself. Thus the only object that needs destroyed +// +//***************************************************************************** +BinInterface::~BinInterface() +{ + delete alloca; +} Index: llvm/lib/Reoptimizer/BinInterface/sparcbin.h diff -u llvm/lib/Reoptimizer/BinInterface/sparcbin.h:1.2 llvm/lib/Reoptimizer/BinInterface/sparcbin.h:1.3 --- llvm/lib/Reoptimizer/BinInterface/sparcbin.h:1.2 Sat Dec 14 19:32:13 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcbin.h Sun Dec 15 05:07:41 2002 @@ -22,147 +22,168 @@ struct regalloc; struct shufflepair; + static const unsigned SECTION_PROLOG =0; static const unsigned SECTION_TRACE =1; class BinInterface { -private: + private: + + Allocator * alloca; // primary stack allocator + fvector itable; // maps an unsigned ID + // to an instruction + + fvector sections; + fvector livein; // pointers to all livein nodes + + // make SURE instr has already has its SELF index + // assigned! + void insert_instr(unsigned instr_id, instruction * instr); + void push_section(); + + + // insertions are delayed to facilitate branch analysis + struct insertion + { + unsigned * begin; + unsigned * end; + unsigned section; + unsigned idstart; + }; + + void process_branch(const insertion & i, + unsigned ** brdest, int scns); + + void construct_merge(int s, int brdest, unsigned map[32], + fvector & regmaps); + + void process_section(unsigned s, unsigned map[32], + fvector & regmaps); + + void process_markgen(unsigned s, unsigned map[32]); + + + fvector queue; + instruction * allocphi(); + + // returns itable index for new live in node + unsigned allocnodelivein(int s, int reg); + unsigned allocnodeshuffles(int s, fvector * shuffles); + int spill_load(int vreg, regmask32 & rmask, + const int memspills[32], int & freereg, + int spills[3], int & spill_cnt, + unsigned * & out); + + void select(regalloc & regs); + + int spillreg(int spillloc, unsigned * & out, + fvector & vregs, regmask & freeregs, + unsigned hwregs[32]); + + + void prepare_exit(const regalloc & regalloc, + fvector * mod, + unsigned * & out); + + unsigned emit_gen(unsigned char * out, const regalloc & regs); + + + public: + + + // Call newepilog() to get the ID of a new epilog section + unsigned newepilog(); + // IDs of prolog and trace sections + + // initial instruction block insertion. specify section number + // and iterator to machine instructions + // (iend is the first instruction not to insert) + unsigned insert(unsigned section, unsigned *ibegin, unsigned * iend); + + // Returns the ID of the first instruction in the section + unsigned begin(unsigned sectionid) + { return (itable[sections[sectionid]])->next; } + // Returns the ID to stop iterating on (header node) + unsigned end (unsigned sectionid) + { return sections[sectionid]; } + + // Find predecessor/sucessor of instructions + unsigned next(unsigned t) + { return itable[t]->next; } + + unsigned prev(unsigned t) + { return itable[t]->prev; } + + // Delete any instruction by instruction ID + void remove(unsigned); + + // Move instruction mbegin and stopping before mend to directly after + // an instruction. (mbegin and mend do not point to consecutive + // instruction numbers) + void move(unsigned mbegin, unsigned mend, unsigned after_this); + + // Swap the locations of 2 instructions + void swap(unsigned a, unsigned b); + + // Get the opcode associated with a given instruction + unsigned getopcode(unsigned); + + // Query to get the RS1/RS2/CC0 generation information. Returns + // the instruction it is getting the result from. Make + // SURE the instruction is not a branch or PHI node or else + // these results will be gibberish + unsigned getrs1(unsigned); + unsigned getrs2(unsigned); + unsigned getcc0(unsigned); + + + + // Instructions exist outside of any section when created + // you must place them using 'move'! + + // New relative branch, destination is an instruction ID (returns + // branch instruction ID) + unsigned newbranch(unsigned op, unsigned dest); + + // New absolute address branch + unsigned newabsbranch(unsigned op, void * dest); + + // General operation generation + unsigned newalu (unsigned op, unsigned rs1, unsigned rs2); + unsigned newalucc(unsigned op, unsigned rs1, unsigned rs2, unsigned cc0); + + // Must be called before any manipulations -> + // this translates the instruction insert with 'insert' + // into SSA form + + // The liveout is a mask of registers that are live out + // if you want to make it assume all registers are pot + // live out -> pass in 0xFFFFFFFE (reg 0 cannot be liveout) + void reduce(); + void complete(); + void liveout(unsigned live); + + + // Predicts size (within a power of 2) of neccesary code + // buffer + unsigned predict(); + + // Emit code into user specified buffer + unsigned emit(unsigned char * out); - Allocator *alloca; // primary stack allocator - fvector itable; // maps an unsigned ID - // to an instruction - - fvector sections; - fvector livein; // pointers to all livein nodes - - // make SURE instr has already has its SELF index - // assigned! - void insert_instr(unsigned instr_id, instruction * instr); - void push_section(); - - - // insertions are delayed to facilitate branch analysis - - struct insertion - { - unsigned * begin; - unsigned * end; - unsigned section; - unsigned idstart; - }; - - void process_branch(const insertion & i, unsigned ** brdest, int scns); - void process_section(unsigned s, unsigned map[32],fvector & regmaps); - void process_markgen(unsigned s, unsigned map[32],fvector & regmaps); - - - fvector queue; - instruction * allocphi(); - - // returns itable index for new live in node - unsigned allocnodelivein(int s, int reg); - unsigned allocnodeshuffles(int s, fvector * shuffles); - int spill_load(int vreg, regmask32 & rmask,const int memspills[32], int & freereg, int spills[3], int & spill_cnt, unsigned * & out); - void select(regalloc & regs); - - int spillreg(int spillloc, unsigned * & out, fvector & vregs, regmask & freeregs, unsigned hwregs[32]); - - - void prepare_exit(const regalloc & regalloc, fvector * mod, unsigned * & out); - unsigned emit_gen(unsigned char * out, const regalloc & regs); - - -public: - - - // Call newepilog() to get the ID of a new epilog section - unsigned newepilog(); - // IDs of prolog and trace sections - - // initial instruction block insertion. specify section number - // and iterator to machine instructions - // (iend is the first instruction not to insert) - unsigned insert(unsigned section, unsigned *ibegin, unsigned * iend); - - // Returns the ID of the first instruction in the section - unsigned begin(unsigned sectionid) { return (itable[sections[sectionid]])->next; } - // Returns the ID to stop iterating on (header node) - unsigned end (unsigned sectionid) { return sections[sectionid]; } - - // Find predecessor/sucessor of instructions - unsigned next(unsigned t) { return itable[t]->next; } - unsigned prev(unsigned t) { return itable[t]->prev; } - - // Delete any instruction by instruction ID - void remove(unsigned); - - // Move instruction mbegin and stopping before mend to directly after - // an instruction. (mbegin and mend do not point to consecutive - // instruction numbers) - void move(unsigned mbegin, unsigned mend, unsigned after_this); - - // Swap the locations of 2 instructions - void swap(unsigned a, unsigned b); - - // Get the opcode associated with a given instruction - unsigned getopcode(unsigned); - - // Query to get the RS1/RS2/CC0 generation information. Returns - // the instruction it is getting the result from. Make - // SURE the instruction is not a branch or PHI node or else - // these results will be gibberish - unsigned getrs1(unsigned); - unsigned getrs2(unsigned); - unsigned getcc0(unsigned); - - - - // Instructions exist outside of any section when created - // you must place them using 'move'! - - // New relative branch, destination is an instruction ID (returns - // branch instruction ID) - unsigned newbranch(unsigned op, unsigned dest); - - // New absolute address branch - unsigned newabsbranch(unsigned op, void * dest); - - // General operation generation - unsigned newalu (unsigned op, unsigned rs1, unsigned rs2); - unsigned newalucc (unsigned op, unsigned rs1, unsigned rs2, unsigned cc0); - - // Must be called before any manipulations -> - // this translates the instruction insert with 'insert' - // into SSA form - - // The liveout is a mask of registers that are live out - // if you want to make it assume all registers are pot - // live out -> pass in 0xFFFFFFFE (reg 0 cannot be liveout) - void reduce(); - void complete(); - void liveout(unsigned live); - - - // Predicts size (within a power of 2) of neccesary code - // buffer - unsigned predict(); - - // Emit code into user specified buffer - unsigned emit(unsigned char * out); - - // Debug printing - void print(); - void print(unsigned scn); + // Debug printing + void print(); + void print(unsigned scn); - // Use to reset for a second pass (internally stack allocation is used) - void clear(); + // Use to reset for a second pass (internally stack allocation is used) + void clear(); - - BinInterface(unsigned instr_count); + BinInterface(unsigned heapsize); + ~BinInterface(); }; #endif Index: llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.5 llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.6 --- llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.5 Sat Dec 14 19:32:14 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp Sun Dec 15 05:07:42 2002 @@ -1,5 +1,5 @@ //***************************************************************************** -// SPARC Instruction Disassembler +// SPARC Instruction Disassembler // // Disassembler API Header // @@ -28,619 +28,686 @@ void sparc_printop_rs1(unsigned instr, int labelrs1) { - if (labelrs1) - printf("l%d", labelrs1); - else - printf("%s", reg_names[RD_FLD(instr, INSTR_RS1)]); + if (labelrs1) + printf("l%d", labelrs1); + else + printf("%s", reg_names[RD_FLD(instr, INSTR_RS1)]); } void sparc_printop_rs2(unsigned instr, int labelrs2) { - if (labelrs2) - printf("l%d", labelrs2); - else - printf("%s", reg_names[RD_FLD(instr, INSTR_RS2)]); + if (labelrs2) + printf("l%d", labelrs2); + else + printf("%s", reg_names[RD_FLD(instr, INSTR_RS2)]); } void sparc_printop_rrd(unsigned instr, int labelrrd) { - if (labelrrd) - printf("l%d", labelrrd); - else - printf("%s", reg_names[RD_FLD(instr, INSTR_RD)]); + if (labelrrd) + printf("l%d", labelrrd); + else + printf("%s", reg_names[RD_FLD(instr, INSTR_RD)]); } void sparc_printbr(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) { - // look at the OP2 field - if (RD_FLD(instr,INSTR_OP2)==OP2_ILLTRAP) - printf("ILLTRAP"); - else if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI) - { - if (RD_FLD(instr, INSTR_RD) == 0) - printf("NOP"); - else - { - printf("SETHI %%hi(%08X), ", RD_FLD(instr, INSTR_IMM22) << 10); - sparc_printop_rrd(instr, labelrd); - } - } - else if (RD_FLD(instr, INSTR_OP2)==OP2_BICC) - { - printf("b%s disp:%08X",icond_names[RD_FLD(instr, INSTR_COND_H)], SIGN_EXTEND(RD_FLD(instr,INSTR_DISP22),22)); - } - else if (RD_FLD(instr, INSTR_OP2)==OP2_BPR) - { - //A, RCOND_H, D16HI, P, RS1, D16LO - printf("P%s%s%s ", rcond_names[RD_FLD(instr, INSTR_RCOND_H)], - RD_FLD(instr, INSTR_A) ? ",a" : "", - RD_FLD(instr, INSTR_P) ? ",pt" : ",pn"); - sparc_printop_rs1(instr, labelrs1); - } - else if (RD_FLD(instr, INSTR_OP2)==OP2_FB) - { - // cond, A, disp22 - printf("%s%s %08X", fcond_names[RD_FLD(instr, INSTR_COND_H)], - RD_FLD(instr, INSTR_A) ? ",a" : "", - RD_FLD(instr, INSTR_DISP22)); - } - else{ - printf("Unknown:OP=0b00 OP2 = 0x%04X", RD_FLD(instr, INSTR_OP2)); - assert(0); - } -} - -void sparc_printalu(char * basename , unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) -{ - // OP=OP_2 : RD, OP3, RS1: {I=0 -> RS2 I=1->SIMM13} - if (RD_FLD(instr, INSTR_I)==0) - { - printf("%s ", basename); - if (!labels) - printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); - sparc_printop_rs1(instr, labelrs1); - printf(" ,"); - sparc_printop_rs2(instr, labelrs2); - } - else - { - printf("%s ", basename); - if (!labels) - printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); - sparc_printop_rs1(instr, labelrs1); - printf(" , %d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - } -} - -void sparc_printshf(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) -{ - //OP=OP_2: RD, OP_3 RS1: {I=0 -> X & RS2 ,I=1 -> {X=0 -> SHCNT32 X=1->SHCNT64 }} - if (RD_FLD(instr, INSTR_I)==0) - { - printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64)); - if (!labels) - printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); - - sparc_printop_rs1(instr, labelrs1); - printf(", "); - sparc_printop_rs2(instr, labelrs2); - } - else - { - printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64)); - if (!labels) - printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); - - sparc_printop_rs1(instr, labelrs1); - printf(", 0x%04X", (RD_FLD(instr, INSTR_X)==0 ? RD_FLD(instr, INSTR_SHCNT32) : RD_FLD(instr, INSTR_SHCNT64))); - } + // look at the OP2 field + if (RD_FLD(instr,INSTR_OP2)==OP2_ILLTRAP) + printf("ILLTRAP"); + else if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI) + { + if (RD_FLD(instr, INSTR_RD) == 0) + printf("NOP"); + else + { + printf("SETHI %%hi(%08X), ", RD_FLD(instr, INSTR_IMM22) << 10); + sparc_printop_rrd(instr, labelrd); + } + } + else if (RD_FLD(instr, INSTR_OP2)==OP2_BICC) + { + printf("b%s disp:%08X",icond_names[RD_FLD(instr, INSTR_COND_H)], SIGN_EXTEND(RD_FLD(instr,INSTR_DISP22),22)); + } + else if (RD_FLD(instr, INSTR_OP2)==OP2_BPR) + { + //A, RCOND_H, D16HI, P, RS1, D16LO + printf("P%s%s%s ", rcond_names[RD_FLD(instr, INSTR_RCOND_H)], + RD_FLD(instr, INSTR_A) ? ",a" : "", + RD_FLD(instr, INSTR_P) ? ",pt" : ",pn"); + sparc_printop_rs1(instr, labelrs1); + } + else if (RD_FLD(instr, INSTR_OP2)==OP2_FB) + { + // cond, A, disp22 + printf("%s%s %08X", fcond_names[RD_FLD(instr, INSTR_COND_H)], + RD_FLD(instr, INSTR_A) ? ",a" : "", + RD_FLD(instr, INSTR_DISP22)); + } + else{ + printf("Unknown:OP=0b00 OP2 = 0x%04X", RD_FLD(instr, INSTR_OP2)); + assert(0); + } +} + +void sparc_printalu(char * basename , unsigned instr, bool labels, + int labelrs1, int labelrs2, int labelrd, int labelccf) +{ + // OP=OP_2 : RD, OP3, RS1: {I=0 -> RS2 I=1->SIMM13} + if (RD_FLD(instr, INSTR_I)==0) + { + printf("%s ", basename); + if (!labels) + printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); + sparc_printop_rs1(instr, labelrs1); + printf(" ,"); + sparc_printop_rs2(instr, labelrs2); + } + else + { + printf("%s ", basename); + if (!labels) + printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); + sparc_printop_rs1(instr, labelrs1); + printf(" , %d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + } +} + +void sparc_printshf(char * basename, unsigned instr, bool labels, + int labelrs1, int labelrs2, int labelrd, int labelccf) +{ + //OP=OP_2: RD, OP_3 RS1: {I=0 -> X & RS2 ,I=1 -> + // {X=0 -> SHCNT32 X=1->SHCNT64 }} + if (RD_FLD(instr, INSTR_I)==0) + { + printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64)); + if (!labels) + printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); + + sparc_printop_rs1(instr, labelrs1); + printf(", "); + sparc_printop_rs2(instr, labelrs2); + } + else + { + printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64)); + if (!labels) + printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); + + sparc_printop_rs1(instr, labelrs1); + printf(", 0x%04X", (RD_FLD(instr, INSTR_X)==0 + ? RD_FLD(instr, INSTR_SHCNT32) + : RD_FLD(instr, INSTR_SHCNT64))); + } } // Op2 class instructions -void sparc_printfpu(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) +void sparc_printfpu(unsigned instr, bool labels, int labelrs1, int labelrs2, + int labelrd, int labelccf) { - switch(RD_FLD(instr, INSTR_OPF) &~ OPF_MASK_ON) - { - case OPF_FADDn: - printf("FADDn"); - return; - case OPF_FSUBn: - printf("FSUBn"); - return; - case OPF_FMOVn: - printf("FMOVn"); - return; - case OPF_FNEGn: - printf("FNEGn"); - return; - case OPF_FABSn: - printf("FABSn"); - return; - case OPF_FMULn: - printf("FMULn"); - return; - case OPF_FDIVn: - printf("FDIVn"); - return; - case OPF_FSQRTn: - printf("FSQRTn"); - return; - } - switch (RD_FLD(instr, INSTR_OPF) &~OPF_MASK_TO) - { - case OPF_FxTOt: - printf("FxTOt"); - return; - case OPF_FiTOt: - printf("FiTOt"); - return; - } - - switch(RD_FLD(instr, INSTR_OPF)) - { - case OPF_FsTOx: - printf("OPF_FsTOx"); - return; - case OPF_FsTOi: - printf("OPF_FsTOi"); - return; - case OPF_FsTOd: - printf("OPF_FsTOd"); - return; - case OPF_FsTOq: - printf("OPF_FsTOq"); - return; - case OPF_FdTOx: - printf("OPF_FdTOx"); - return; - case OPF_FdTOi: - printf("OPF_FdTOi"); - return; - case OPF_FqTOx: - printf("OPF_FqTOx"); - return; - case OPF_FdTOs: - printf("OPF_FdTOs"); - return; - case OPF_FdTOq: - printf("OPF_FdTOq"); - return; - case OPF_FqTOi: - printf("OPF_FqTOi"); - return; - case OPF_FqTOs: - printf("OPF_FqTOs"); - return; - case OPF_FqTOd: - printf("OPF_FqTOd"); - return; - case OPF_FsMULd: - printf("OPF_FsMULd"); - return; - case OPF_FdMULq: - printf("OPF_FdMULq"); - return; - } - - assert(0); // we don't know the FPU instruction yet -} - -void sparc_print2(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) -{ - switch(RD_FLD(instr, INSTR_OP3)) - { - - case OP3_MOVcc: - { - printf("mov%s(%s) ", icond_names[RD_FLD(instr, INSTR_COND_L)], - cc_names[(RD_FLD(instr, INSTR_CC2) << 2) | (RD_FLD(instr, INSTR_MOV_CC1) << 1) | RD_FLD(instr, INSTR_MOV_CC0)]); - - if (!labels) + switch(RD_FLD(instr, INSTR_OPF) &~ OPF_MASK_ON) + { + case OPF_FADDn: + printf("FADDn"); + return; + case OPF_FSUBn: + printf("FSUBn"); + return; + case OPF_FMOVn: + printf("FMOVn"); + return; + case OPF_FNEGn: + printf("FNEGn"); + return; + case OPF_FABSn: + printf("FABSn"); + return; + case OPF_FMULn: + printf("FMULn"); + return; + case OPF_FDIVn: + printf("FDIVn"); + return; + case OPF_FSQRTn: + printf("FSQRTn"); + return; + } + switch (RD_FLD(instr, INSTR_OPF) &~OPF_MASK_TO) + { + case OPF_FxTOt: + printf("FxTOt"); + return; + case OPF_FiTOt: + printf("FiTOt"); + return; + } + + switch(RD_FLD(instr, INSTR_OPF)) + { + case OPF_FsTOx: + printf("OPF_FsTOx"); + return; + case OPF_FsTOi: + printf("OPF_FsTOi"); + return; + case OPF_FsTOd: + printf("OPF_FsTOd"); + return; + case OPF_FsTOq: + printf("OPF_FsTOq"); + return; + case OPF_FdTOx: + printf("OPF_FdTOx"); + return; + case OPF_FdTOi: + printf("OPF_FdTOi"); + return; + case OPF_FqTOx: + printf("OPF_FqTOx"); + return; + case OPF_FdTOs: + printf("OPF_FdTOs"); + return; + case OPF_FdTOq: + printf("OPF_FdTOq"); + return; + case OPF_FqTOi: + printf("OPF_FqTOi"); + return; + case OPF_FqTOs: + printf("OPF_FqTOs"); + return; + case OPF_FqTOd: + printf("OPF_FqTOd"); + return; + case OPF_FsMULd: + printf("OPF_FsMULd"); + return; + case OPF_FdMULq: + printf("OPF_FdMULq"); + return; + } + + assert(0); // we don't know the FPU instruction yet +} + +void sparc_print2(unsigned instr, bool labels, int labelrs1, int labelrs2, + int labelrd, int labelccf) +{ + switch(RD_FLD(instr, INSTR_OP3)) + { + + case OP3_MOVcc: + { + printf("mov%s(%s) ", icond_names[RD_FLD(instr, INSTR_COND_L)], + cc_names[(RD_FLD(instr, INSTR_CC2) << 2) | (RD_FLD(instr, INSTR_MOV_CC1) << 1) | RD_FLD(instr, INSTR_MOV_CC0)]); + + if (!labels) printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); - - if (RD_FLD(instr, INSTR_I)==0) // RS2 + + if (RD_FLD(instr, INSTR_I)==0) // RS2 sparc_printop_rs2(instr, labelrs2); - else - printf("%d", SIGN_EXTEND(RD_FLD(instr, INSTR_SIMM11), 11)); - - - return; - } - - - case OP3_ADD: - sparc_printalu("ADD", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_ADDcc: - sparc_printalu("ADDcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_ADDC: - sparc_printalu("ADDC", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_ADDCcc: - sparc_printalu("ADDCcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_AND: - sparc_printalu("AND", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_ANDcc: - sparc_printalu("ANDcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_OR: - sparc_printalu("OR", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_ORcc: - sparc_printalu("ORcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_XOR: - sparc_printalu("XOR", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_XORcc: - sparc_printalu("XORcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_SUB: - sparc_printalu("SUB", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_SUBcc: - sparc_printalu("SUBcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_ANDN: - sparc_printalu("ANDN", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_ANDNcc: - sparc_printalu("ANDNcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_ORN: - sparc_printalu("ORN", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_ORNcc: - sparc_printalu("ORNcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_XNOR: - sparc_printalu("XNOR", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_XNORcc: - sparc_printalu("XNORcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_SUBC: - sparc_printalu("SUBC", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_SUBCcc: - sparc_printalu("SUBCcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_MULX: - sparc_printalu("MULX", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_SDIVX: - sparc_printalu("SDIVX", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_UDIVX: - sparc_printalu("UDIVX", instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_SLL: - sparc_printshf("SLL",instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - case OP3_SRL: - sparc_printshf("SRL",instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - case OP3_SRA: - sparc_printshf("SRA",instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_DONERETRY: - { - if (RD_FLD(instr, INSTR_FCN)==FCN_DONE) - printf("DONE"); - else if (RD_FLD(instr, INSTR_FCN)==FCN_RETRY) - printf("RETRY"); - return; - } - - case OP3_FCMP: - { - unsigned fop_n =RD_FLD(instr, INSTR_OPF) &~ OPF_MASK_ON; - if (fop_n==OPF_FCMPn) - printf("FCMP"); - else if (fop_n==OPF_FCMPEn) - printf("FCMPE"); - return; - } - - case OP3_FPU: - sparc_printfpu(instr, labels, labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_FLUSH: //OP=OP_2 RS1 {I=0 -> rs2, I=1->simm13} - printf("OP3_FLUSH"); - return; - case OP3_FLUSHW: //OP=OP_2 I = 0 - printf("OP3_FLUSHW"); - return; - case OP3_JMPL: //OP=OP_2 RD, RS1 {I=0-> RS2, I=1->SIMM13} - if (RD_FLD(instr, INSTR_I)==0) - { - printf("jmpl link:"); - sparc_printop_rrd(instr, labelrd); - printf(", to: "); - sparc_printop_rs1(instr, labelrs1); - printf("+"); - sparc_printop_rs2(instr, labelrs2); - } - else - { - printf("jmpl link:"); - sparc_printop_rrd(instr, labelrd); - printf(", to: "); - sparc_printop_rs1(instr, labelrs1); - printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - } - return; - - case OP3_POPC: - printf("POPC ????"); - return; - - case OP3_RETURN: - if (RD_FLD(instr, INSTR_I) == 0) - { - printf("return "); - sparc_printop_rs1(instr, labelrs1); - printf("+"); - sparc_printop_rs2(instr, labelrs2); - } - else - { - printf("return "); - sparc_printop_rs1(instr, labelrs1); - printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - } - return; - - case OP3_SAVE: - if (RD_FLD(instr, INSTR_I) == 0) - { - printf("save "); - sparc_printop_rs1(instr, labelrs1); - printf(", "); - sparc_printop_rs2(instr, labelrs2); - printf(", "); - sparc_printop_rrd(instr, labelrd); - } - else - { - printf("save "); - sparc_printop_rs1(instr, labelrs1); - printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - sparc_printop_rrd(instr, labelrd); - } - return; - - case OP3_RESTORE: - if (RD_FLD(instr, INSTR_I) == 0) - { - printf("restore "); - sparc_printop_rs1(instr, labelrs1); - printf(", "); - sparc_printop_rs2(instr, labelrs2); - printf(", "); - sparc_printop_rrd(instr, labelrd); - } - else - { - printf("restore "); - sparc_printop_rs1(instr, labelrs1); - printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - sparc_printop_rrd(instr, labelrd); - } - return; - - - } - - printf("Unknown:OP=0b10 OP3 = 0x%04X", RD_FLD(instr, INSTR_OP3)); - assert(0); -} - -void sparc_printload(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd , int labelccf) -{ - if (RD_FLD(instr, INSTR_I)==0) - { - printf("%s ", basename); - if (!labels) - { - sparc_printop_rrd(instr, labelrd); - printf(", "); - } - sparc_printop_rs1(instr, labelrs1); - printf("+"); - sparc_printop_rs2(instr, labelrs2); - } - else - { - printf("%s ", basename); - if (!labels) - { - sparc_printop_rrd(instr, labelrd); - printf(", "); - } - sparc_printop_rs1(instr, labelrs1); - printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - } -} - -void sparc_printstore(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd , int labelccf) -{ - if (RD_FLD(instr, INSTR_I)==0) - { - printf("%s ", basename); - sparc_printop_rrd(instr, labelrd); - printf(", "); - sparc_printop_rs1(instr, labelrs1); - printf("+"); - sparc_printop_rs2(instr, labelrs2); - - } - else - { - printf("%s ", basename); - sparc_printop_rrd(instr, labelrd); - printf(", "); - sparc_printop_rs1(instr, labelrs1); - printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); - } -} -void sparc_print3(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) -{ -//#define OP3_LDFA 0b110000 //OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13} -//#define OP3_LDDFA 0b110011 //OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13} -//#define OP3_LDQFA 0b110010 //OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13} -//#define OP3_LDSTUB 0b001101 //OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13} -//#define OP3_LDSTUBA 0b011101 //OP=OP_3 RD, RS1 {I=0->RS2, IMM_ASI, I=1->SIMM13} - switch(RD_FLD(instr, INSTR_OP3)) - { - //OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13} - case OP3_LDSTUB: - sparc_printload("LDSTUB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_STB: - sparc_printstore("STB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_STH: - sparc_printstore("STH", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_STW: - sparc_printstore("STW", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_STX: - sparc_printstore("STX", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_LDSB: - sparc_printload("LDSB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_LDSH: - sparc_printload("LDSH", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_LDSW: - sparc_printload("LDSW", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_LDUB: - sparc_printload("LDUB", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_LDUH: - sparc_printload("LDUH", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_LDUW: - sparc_printload("LDUW", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_LDX: - sparc_printload("LDX", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_CASA: - if (RD_FLD(instr, INSTR_I)==0) - { - if (!labels) - printf("CASA [r%d] %%%d, r%d, r%d", RD_FLD(instr, INSTR_RS1),RD_FLD(instr, INSTR_IMMASI), RD_FLD(instr, INSTR_RS2), RD_FLD(instr, INSTR_RD)); - else - printf("CASA [l%d] %%%d, l%d, l%d", labelrs1,RD_FLD(instr, INSTR_IMMASI), labelrs2, labelrd); - } - else - { - if (!labels) - printf("CASA [r%d] , r%d, r%d", RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_RS2), RD_FLD(instr, INSTR_RD)); - else - printf("CASA [l%d] , l%d, l%d", labelrs1, labelrs2, labelrd); - } - - sparc_printalu("CASA", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - - return; - - case OP3_CASXA: - sparc_printalu("CASXA", instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - case OP3_STFA: - sparc_printalu("STFA",instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - case OP3_STDFA: - sparc_printalu("STDFA",instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - case OP3_STQFA: - sparc_printalu("STQFA",instr,labels,labelrs1, labelrs2, labelrd, labelccf); - return; - - case OP3_PREFETCH: - printf("PREFETCH ??? "); - return; - - case OP3_PREFETCHA: - printf("PREFETCHA ??? "); - return; - } + else + printf("%d", SIGN_EXTEND(RD_FLD(instr, INSTR_SIMM11), 11)); + + + return; + } + + + case OP3_ADD: + sparc_printalu("ADD", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_ADDcc: + sparc_printalu("ADDcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_ADDC: + sparc_printalu("ADDC", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_ADDCcc: + sparc_printalu("ADDCcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_AND: + sparc_printalu("AND", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_ANDcc: + sparc_printalu("ANDcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_OR: + sparc_printalu("OR", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_ORcc: + sparc_printalu("ORcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_XOR: + sparc_printalu("XOR", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_XORcc: + sparc_printalu("XORcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_SUB: + sparc_printalu("SUB", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_SUBcc: + sparc_printalu("SUBcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_ANDN: + sparc_printalu("ANDN", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_ANDNcc: + sparc_printalu("ANDNcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_ORN: + sparc_printalu("ORN", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_ORNcc: + sparc_printalu("ORNcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_XNOR: + sparc_printalu("XNOR", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_XNORcc: + sparc_printalu("XNORcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_SUBC: + sparc_printalu("SUBC", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_SUBCcc: + sparc_printalu("SUBCcc", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_MULX: + sparc_printalu("MULX", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_SDIVX: + sparc_printalu("SDIVX", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_UDIVX: + sparc_printalu("UDIVX", instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_SLL: + sparc_printshf("SLL",instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + case OP3_SRL: + sparc_printshf("SRL",instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + case OP3_SRA: + sparc_printshf("SRA",instr, labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_DONERETRY: + { + if (RD_FLD(instr, INSTR_FCN)==FCN_DONE) + printf("DONE"); + else if (RD_FLD(instr, INSTR_FCN)==FCN_RETRY) + printf("RETRY"); + return; + } + + case OP3_FCMP: + { + unsigned fop_n =RD_FLD(instr, INSTR_OPF) &~ OPF_MASK_ON; + if (fop_n==OPF_FCMPn) + printf("FCMP"); + else if (fop_n==OPF_FCMPEn) + printf("FCMPE"); + return; + } + + case OP3_FPU: + sparc_printfpu(instr, labels, labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_FLUSH: //OP=OP_2 RS1 {I=0 -> rs2, I=1->simm13} + printf("OP3_FLUSH"); + return; + case OP3_FLUSHW: //OP=OP_2 I = 0 + printf("OP3_FLUSHW"); + return; + case OP3_JMPL: //OP=OP_2 RD, RS1 {I=0-> RS2, I=1->SIMM13} + if (RD_FLD(instr, INSTR_I)==0) + { + printf("jmpl link:"); + sparc_printop_rrd(instr, labelrd); + printf(", to: "); + sparc_printop_rs1(instr, labelrs1); + printf("+"); + sparc_printop_rs2(instr, labelrs2); + } + else + { + printf("jmpl link:"); + sparc_printop_rrd(instr, labelrd); + printf(", to: "); + sparc_printop_rs1(instr, labelrs1); + printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + } + return; + + case OP3_POPC: + printf("POPC ????"); + return; + + case OP3_RETURN: + if (RD_FLD(instr, INSTR_I) == 0) + { + printf("return "); + sparc_printop_rs1(instr, labelrs1); + printf("+"); + sparc_printop_rs2(instr, labelrs2); + } + else + { + printf("return "); + sparc_printop_rs1(instr, labelrs1); + printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + } + return; + + case OP3_SAVE: + if (RD_FLD(instr, INSTR_I) == 0) + { + printf("save "); + sparc_printop_rs1(instr, labelrs1); + printf(", "); + sparc_printop_rs2(instr, labelrs2); + printf(", "); + sparc_printop_rrd(instr, labelrd); + } + else + { + printf("save "); + sparc_printop_rs1(instr, labelrs1); + printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + sparc_printop_rrd(instr, labelrd); + } + return; + + case OP3_RESTORE: + if (RD_FLD(instr, INSTR_I) == 0) + { + printf("restore "); + sparc_printop_rs1(instr, labelrs1); + printf(", "); + sparc_printop_rs2(instr, labelrs2); + printf(", "); + sparc_printop_rrd(instr, labelrd); + } + else + { + printf("restore "); + sparc_printop_rs1(instr, labelrs1); + printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + sparc_printop_rrd(instr, labelrd); + } + return; + + + } + + printf("Unknown:OP=0b10 OP3 = 0x%04X", RD_FLD(instr, INSTR_OP3)); + assert(0); +} + +void sparc_printload(char * basename, unsigned instr, bool labels, + int labelrs1, int labelrs2, int labelrd , int labelccf) +{ + if (RD_FLD(instr, INSTR_I)==0) + { + printf("%s ", basename); + if (!labels) + { + sparc_printop_rrd(instr, labelrd); + printf(", "); + } + sparc_printop_rs1(instr, labelrs1); + printf("+"); + sparc_printop_rs2(instr, labelrs2); + } + else + { + printf("%s ", basename); + if (!labels) + { + sparc_printop_rrd(instr, labelrd); + printf(", "); + } + sparc_printop_rs1(instr, labelrs1); + printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + } +} + +void sparc_printstore(char * basename, unsigned instr, bool labels, + int labelrs1, int labelrs2, int labelrd , int labelccf) +{ + if (RD_FLD(instr, INSTR_I)==0) + { + printf("%s ", basename); + sparc_printop_rrd(instr, labelrd); + printf(", "); + sparc_printop_rs1(instr, labelrs1); + printf("+"); + sparc_printop_rs2(instr, labelrs2); + + } + else + { + printf("%s ", basename); + sparc_printop_rrd(instr, labelrd); + printf(", "); + sparc_printop_rs1(instr, labelrs1); + printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + } +} +void sparc_print3(unsigned instr, bool labels, int labelrs1, int labelrs2, + int labelrd, int labelccf) +{ + // OP3_LDF OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13} + // OP3_LDDFA OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13} + // OP3_LDQFA OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13} + // OP3_LDSTUB OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13} + // OP3_LDSTUBA OP=OP_3 RD, RS1 {I=0->RS2, IMM_ASI, I=1->SIMM13} + + + switch(RD_FLD(instr, INSTR_OP3)) + { + //OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13} + case OP3_LDSTUB: + sparc_printload("LDSTUB", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_STB: + sparc_printstore("STB", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_STH: + sparc_printstore("STH", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_STW: + sparc_printstore("STW", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_STX: + sparc_printstore("STX", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_LDSB: + sparc_printload("LDSB", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_LDSH: + sparc_printload("LDSH", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_LDSW: + sparc_printload("LDSW", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_LDUB: + sparc_printload("LDUB", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_LDUH: + sparc_printload("LDUH", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_LDUW: + sparc_printload("LDUW", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_LDX: + sparc_printload("LDX", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_CASA: + if (RD_FLD(instr, INSTR_I)==0) + { + if (!labels) + printf("CASA [r%d] %%%d, r%d, r%d", + RD_FLD(instr, INSTR_RS1), + RD_FLD(instr, INSTR_IMMASI), + RD_FLD(instr, INSTR_RS2), + RD_FLD(instr, INSTR_RD)); + + else + printf("CASA [l%d] %%%d, l%d, l%d", + labelrs1, + RD_FLD(instr, INSTR_IMMASI), + labelrs2, + labelrd); + } + else + { + if (!labels) + printf("CASA [r%d] , r%d, r%d", + RD_FLD(instr, INSTR_RS1), + RD_FLD(instr, INSTR_RS2), + RD_FLD(instr, INSTR_RD)); + else + printf("CASA [l%d] , l%d, l%d", labelrs1, labelrs2, labelrd); + } + + sparc_printalu("CASA", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + + return; + + case OP3_CASXA: + sparc_printalu("CASXA", instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + case OP3_STFA: + sparc_printalu("STFA",instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + case OP3_STDFA: + sparc_printalu("STDFA",instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + case OP3_STQFA: + sparc_printalu("STQFA",instr,labels, + labelrs1, labelrs2, labelrd, labelccf); + return; + + case OP3_PREFETCH: + printf("PREFETCH ??? "); + return; + + case OP3_PREFETCHA: + printf("PREFETCHA ??? "); + return; + } - printf("Unknown OP_3: OP3 = %08X", RD_FLD(instr, INSTR_OP3)); - assert(0); + printf("Unknown OP_3: OP3 = %08X", RD_FLD(instr, INSTR_OP3)); + assert(0); } void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf) { - if (RD_FLD(instr,INSTR_OP)==OP_CALL) - printf("CALL disp:+%08X", instr & 0x3FFFFFFF); - else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH) - sparc_printbr(instr,true,labelrs1, labelrs2, labelrd, labelccf); - else if (RD_FLD(instr,INSTR_OP)==OP_2) - sparc_print2(instr,true,labelrs1, labelrs2, labelrd, labelccf); - else if (RD_FLD(instr,INSTR_OP)==OP_3) - sparc_print3(instr,true,labelrs1, labelrs2, labelrd, labelccf); + if (RD_FLD(instr,INSTR_OP)==OP_CALL) + printf("CALL disp:+%08X", instr & 0x3FFFFFFF); + else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH) + sparc_printbr(instr,true,labelrs1, labelrs2, labelrd, labelccf); + else if (RD_FLD(instr,INSTR_OP)==OP_2) + sparc_print2(instr,true,labelrs1, labelrs2, labelrd, labelccf); + else if (RD_FLD(instr,INSTR_OP)==OP_3) + sparc_print3(instr,true,labelrs1, labelrs2, labelrd, labelccf); } void sparc_print(unsigned instr) { - if (RD_FLD(instr,INSTR_OP)==OP_CALL) - printf("CALL disp:+%08X", instr & 0x3FFFFFFF); - else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH) - sparc_printbr(instr,false,0, 0, 0, 0); - else if (RD_FLD(instr,INSTR_OP)==OP_2) - sparc_print2(instr,false,0, 0, 0, 0); - else if (RD_FLD(instr,INSTR_OP)==OP_3) - sparc_print3(instr,false,0, 0, 0, 0 ); + if (RD_FLD(instr,INSTR_OP)==OP_CALL) + printf("CALL disp:+%08X", instr & 0x3FFFFFFF); + else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH) + sparc_printbr(instr,false,0, 0, 0, 0); + else if (RD_FLD(instr,INSTR_OP)==OP_2) + sparc_print2(instr,false,0, 0, 0, 0); + else if (RD_FLD(instr,INSTR_OP)==OP_3) + sparc_print3(instr,false,0, 0, 0, 0 ); } Index: llvm/lib/Reoptimizer/BinInterface/sparcdis.h diff -u llvm/lib/Reoptimizer/BinInterface/sparcdis.h:1.4 llvm/lib/Reoptimizer/BinInterface/sparcdis.h:1.5 --- llvm/lib/Reoptimizer/BinInterface/sparcdis.h:1.4 Sat Dec 14 19:32:18 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcdis.h Sun Dec 15 05:07:46 2002 @@ -1,36 +1,36 @@ -//***************************************************************************** -// SPARC Instruction Disassembler -// -// Disassembler API Header -// -// * Initial implementation -// * Added support for MOVcc (somehow I missed it?!) -// * Added support for pseudo-disassembly -// ( In the print routine for bin-interface we want -// to be able to print the internal SSA form with -// labels instead of registers. And we wish to -// ommit RD from the view when we are not explicitly -// reading from it) -// -// Todo: -// * On the instructions that don't read from RD -// do not print the label field (we get l-1 when we print) -// -// 2002 Cameron Buschardt -//***************************************************************************** - -#ifndef __SPARCDIS__ -#define __SPARCDIS__ -// Conventional Disassembly. Prints instruction (no newline) -void sparc_print(unsigned instr); - -// Pseudo disasm -// uses the integers in labelrs1, labelrs2, labelrd, and labelccf as -// gen labels for the parameter sources -// instead of printing rxx for rs1, it will print l__labelrs1__ -void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf); - - -#endif - - +//***************************************************************************** +// SPARC Instruction Disassembler +// +// Disassembler API Header +// +// * Initial implementation +// * Added support for MOVcc (somehow I missed it?!) +// * Added support for pseudo-disassembly +// ( In the print routine for bin-interface we want +// to be able to print the internal SSA form with +// labels instead of registers. And we wish to +// ommit RD from the view when we are not explicitly +// reading from it) +// +// Todo: +// * On the instructions that don't read from RD +// do not print the label field (we get l-1 when we print) +// +// 2002 Cameron Buschardt +//***************************************************************************** + +#ifndef __SPARCDIS__ +#define __SPARCDIS__ +// Conventional Disassembly. Prints instruction (no newline) +void sparc_print(unsigned instr); + +// Pseudo disasm +// uses the integers in labelrs1, labelrs2, labelrd, and labelccf as +// gen labels for the parameter sources +// instead of printing rxx for rs1, it will print l__labelrs1__ +void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf); + + +#endif + + Index: llvm/lib/Reoptimizer/BinInterface/sparcpriv.h diff -u llvm/lib/Reoptimizer/BinInterface/sparcpriv.h:1.1 llvm/lib/Reoptimizer/BinInterface/sparcpriv.h:1.2 --- llvm/lib/Reoptimizer/BinInterface/sparcpriv.h:1.1 Sat Dec 14 19:32:27 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcpriv.h Sun Dec 15 05:07:48 2002 @@ -1,99 +1,114 @@ +//***************************************************************************** +// BinInterface private structures and constants +// +// +// +// +// 2002 Cameron Buschardt +//***************************************************************************** + #ifndef __SPARC_PRIV_H__ #define __SPARC_PRIV_H__ #include "fvector.h" + // // Instruction flag definitions -// -#define IF_ALUOP (IF_USR << 1) -#define IF_PHI (IF_USR << 2) +// +#define IF_ALUOP (IF_USR << 1) // generic ALU +#define IF_PHI (IF_USR << 2) // phi node #define IF_NODELIVEIN (IF_USR << 3) // instr field is register to bind to #define IF_REGSHUFFLE (IF_USR << 5) // register shuffle (calls and liveouts) -#define IF_BRINTERNAL (IF_USR << 6) // is this an INTERNAL branch if so use ibranch -#define IF_LIVEOUT (IF_USR << 7) // do we think this instruction is liveout? +#define IF_BRINTERNAL (IF_USR << 6) // is this an INTERNAL branch +#define IF_LIVEOUT (IF_USR << 7) // this instruction is liveout? // a call instruction will spill all the outgoing registers O0->O7 (R8-R15) #define R_CALLSPILLS 0x0000FF00 -#define R_ALLOCREGS (~0 & ~(1 | (1< ssa_to_vreg; // map of SSA Id's to virtual registers - fvector vregs; // virtual register descriptors - int spillreg; - int memspills[32]; - unsigned touched_regs; - unsigned stack_size; - unsigned liveout_regs; - - regalloc(Allocator * alloc) - : ssa_to_vreg(alloc), vregs(alloc) {} + fvector ssa_to_vreg; // map of SSA Id's to virtual registers + fvector vregs; // virtual register descriptors + int spillreg; + int memspills[32]; + unsigned touched_regs; + unsigned stack_size; + unsigned liveout_regs; + + regalloc(Allocator * alloc) + : ssa_to_vreg(alloc), vregs(alloc) {} }; struct shufflepair { - int reg; - int gen; - shufflepair() {} - shufflepair(int r, int g) : reg(r), gen(g) {} + int reg; + int gen; + shufflepair() {} + shufflepair(int r, int g) : reg(r), gen(g) {} }; struct instruction { - unsigned next; - unsigned prev; - unsigned self; - unsigned flags; - - unsigned instr; - union - { - struct - { - unsigned genrs1; - unsigned genrs2; - unsigned genccf; - unsigned genrd; //ingenious SUN.. we can read from RD!?! - } alu; - struct - { - unsigned dest; // id # of destination section - } ibranch; // internal branch - struct - { - unsigned * dest; - } ebranch; // external branch - struct - { - fvector * params; - }phi; - struct - { - unsigned reg; - } livein; - struct - { - fvector * shuffles; - } regshuffle; - }; + unsigned next; + unsigned prev; + unsigned self; + unsigned flags; + + unsigned instr; + union + { + struct + { + unsigned genrs1; + unsigned genrs2; + unsigned genccf; + unsigned genrd; //wonderful SUN.. we can read from RD (STX) + } alu; + struct + { + unsigned dest; // id # of destination section + } ibranch; // internal branch + struct + { + unsigned * dest; + } ebranch; // external branch + struct + { + fvector * params; + }phi; + struct + { + unsigned reg; + } livein; + struct + { + fvector * shuffles; + } regshuffle; + }; }; #endif Index: llvm/lib/Reoptimizer/BinInterface/test.cpp diff -u llvm/lib/Reoptimizer/BinInterface/test.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/test.cpp:1.2 --- llvm/lib/Reoptimizer/BinInterface/test.cpp:1.1 Sat Dec 14 19:32:30 2002 +++ llvm/lib/Reoptimizer/BinInterface/test.cpp Sun Dec 15 05:07:48 2002 @@ -1,3 +1,11 @@ +//***************************************************************************** +// SPARC Binary Interface Test +// +// Simple test and benchmark +// +// 2002 Cameron Buschardt +//***************************************************************************** + #include #include #include "sparc9.h" @@ -10,125 +18,147 @@ #include "sparcbin.h" #include "sparcpriv.h" // Private definitions -//********************************* -// Fast Vector Class -//********************************* +#define arrsize(x) (sizeof(x) / sizeof(*x)) +unsigned ex1_prolog[] = {0x86100008}; +unsigned ex1_trace[] = {0x8400FFFF, 0x8688C002 ,0x12BFFFFE, 0x92026001}; -#define arrsize(x) (sizeof(x) / sizeof(*x)) +void bench1() +{ + BinInterface bin(512*1024); + for (int t=0;t<1000;t++) + { + bin.clear(); + unsigned epilog = bin.newepilog(); + bin.insert(SECTION_PROLOG,ex1_prolog, ex1_prolog + arrsize(ex1_prolog)); + bin.insert(SECTION_TRACE,ex1_trace, ex1_trace + arrsize(ex1_trace)); + bin.complete(); + bin.liveout(3); + bin.liveout(5); -unsigned ex1_prolog[] = {0x86100008}; -unsigned ex1_trace[] = {0x8400FFFF, 0x8688C002 ,0x12BFFFFE, 0x92026001}; -unsigned ex1_epilog[] = {0x81C3E008}; + bin.reduce(); -void bench1() + unsigned buffer[1024]; + unsigned size = bin.emit((unsigned char *)&buffer); + } +} + + +void bench2() { - BinInterface bin(1024); + BinInterface bin(512*1024); + // Generate trace (do a NOP on each reg basically reg-reg move same src/dst) + // Generate prolog (read from random addr into all registers in R_ALLOCREGS except on + unsigned ex2_prolog[32]; + int ex2_pidx = 0; + unsigned mask = R_ALLOCREGS; + for (int k=0;k<32;k++) + if (( mask >> k ) & 1) + ex2_prolog[ex2_pidx++] = MK_LDX_ROFFS(k, R_BP,8*k); + unsigned ex2_trace[32]; + int ex2_tidx = 0; + for (int k=0;k<32;k++) + if (( mask >> k) & 1) + ex2_trace[ex2_tidx++] = MK_MOV_R_R(k,k); + for (int t=0;t<1000;t++) + { + bin.clear(); + unsigned epilog = bin.newepilog(); + bin.insert(SECTION_PROLOG,ex2_prolog, ex2_prolog + ex2_pidx); + int trace_base=bin.insert(SECTION_TRACE,ex2_trace, ex2_trace + ex2_tidx); + bin.complete(); + + // all trace elements are liveout + for (int k=0;k> k ) & 1) - ex2_prolog[ex2_pidx++] = MK_LDX_ROFFS(k, R_BP,8*k); - - // Generate trace (do a NOP on each reg basically reg-reg move same src/dst) - unsigned ex2_trace[32]; - int ex2_tidx = 0; - for (int k=0;k<32;k++) - if (( mask >> k) & 1) - ex2_trace[ex2_tidx++] = MK_MOV_R_R(k,k); - - bin.insert(SECTION_PROLOG,ex2_prolog, ex2_prolog + ex2_pidx); - int trace_base= bin.insert(SECTION_TRACE,ex2_trace, ex2_trace + ex2_tidx); - bin.insert(epilog,NULL, NULL); // no epilog - - bin.complete(); - - // all trace elements are liveout - for (int k=0;k> k ) & 1) + ex2_prolog[ex2_pidx++] = MK_LDX_ROFFS(k, R_BP,8*k); + + // Generate trace (do a NOP on each reg basically reg-reg move same src/dst) + unsigned ex2_trace[32]; + int ex2_tidx = 0; + for (int k=0;k<32;k++) + if (( mask >> k) & 1) + ex2_trace[ex2_tidx++] = MK_MOV_R_R(k,k); + + bin.insert(SECTION_PROLOG,ex2_prolog, ex2_prolog + ex2_pidx); + int trace_base= bin.insert(SECTION_TRACE,ex2_trace, ex2_trace + ex2_tidx); + + bin.complete(); + + // all trace elements are liveout + for (int k=0;k Changes in directory llvm/test/Regression/CFrontend: 2002-12-15-GlobalBoolTest.c added (r1.1) --- Log message: Testcase identified by Brian Gaeke that breaks the C frontend... --- Diffs of the changes: From lattner at cs.uiuc.edu Sun Dec 15 10:21:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 10:21:01 2002 Subject: [llvm-commits] CVS: llvm/lib/VMCore/SymbolTable.cpp Message-ID: <200212151620.KAA17229@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: SymbolTable.cpp updated: 1.26 -> 1.27 --- Log message: planes is not spelled with an O --- Diffs of the changes: Index: llvm/lib/VMCore/SymbolTable.cpp diff -u llvm/lib/VMCore/SymbolTable.cpp:1.26 llvm/lib/VMCore/SymbolTable.cpp:1.27 --- llvm/lib/VMCore/SymbolTable.cpp:1.26 Tue Oct 15 16:26:29 2002 +++ llvm/lib/VMCore/SymbolTable.cpp Sun Dec 15 10:20:23 2002 @@ -262,7 +262,7 @@ delete NewM; } else { - assert(0 && "Two ploanes folded together with overlapping " + assert(0 && "Two planes folded together with overlapping " "value names!"); } } else { From lattner at cs.uiuc.edu Sun Dec 15 10:33:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 10:33:00 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Assembler/2002-12-15-GlobalResolve.ll Message-ID: <200212151632.KAA17332@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Assembler: 2002-12-15-GlobalResolve.ll added (r1.1) --- Log message: Allow folding together two globals through type resolution --- Diffs of the changes: From lattner at cs.uiuc.edu Sun Dec 15 10:43:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 10:43:01 2002 Subject: [llvm-commits] CVS: llvm/lib/VMCore/SymbolTable.cpp Message-ID: <200212151642.KAA17532@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: SymbolTable.cpp updated: 1.27 -> 1.28 --- Log message: Fix bug: Assembler/2002-12-15-GlobalResolve.ll --- Diffs of the changes: Index: llvm/lib/VMCore/SymbolTable.cpp diff -u llvm/lib/VMCore/SymbolTable.cpp:1.27 llvm/lib/VMCore/SymbolTable.cpp:1.28 --- llvm/lib/VMCore/SymbolTable.cpp:1.27 Sun Dec 15 10:20:23 2002 +++ llvm/lib/VMCore/SymbolTable.cpp Sun Dec 15 10:41:52 2002 @@ -229,17 +229,18 @@ // No action } else if (TI != NewPlane.end()) { - // The only thing we are allowing for now is two method prototypes being + // The only thing we are allowing for now is two external global values // folded into one. // - Function *ExistM = dyn_cast(TI->second); - Function *NewM = dyn_cast(V.second); + GlobalValue *ExistGV = dyn_cast(TI->second); + GlobalValue *NewGV = dyn_cast(V.second); - if (ExistM && NewM && ExistM->isExternal() && NewM->isExternal()) { - // Ok we have two external methods. Make all uses of the new one - // use the old one... + if (ExistGV && NewGV && ExistGV->isExternal() && NewGV->isExternal()) { + // Ok we have two external global values. Make all uses of the new + // one use the old one... // - NewM->replaceAllUsesWith(ExistM); + assert(ExistGV->use_empty() && "No uses allowed on untyped value!"); + //NewGV->replaceAllUsesWith(ExistGV); // Now we just convert it to an unnamed method... which won't get // added to our symbol table. The problem is that if we call @@ -254,12 +255,16 @@ InternallyInconsistent = true; // Remove newM from the symtab - NewM->setName(""); + NewGV->setName(""); InternallyInconsistent = false; - // Now we can remove this method from the module entirely... - NewM->getParent()->getFunctionList().remove(NewM); - delete NewM; + // Now we can remove this global from the module entirely... + Module *M = NewGV->getParent(); + if (Function *F = dyn_cast(NewGV)) + M->getFunctionList().remove(F); + else + M->getGlobalList().remove(cast(NewGV)); + delete NewGV; } else { assert(0 && "Two planes folded together with overlapping " From lattner at cs.uiuc.edu Sun Dec 15 11:15:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 11:15:00 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/CFrontend/2002-12-15-GlobalRedefinition.c Message-ID: <200212151714.LAA18359@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/CFrontend: 2002-12-15-GlobalRedefinition.c added (r1.1) --- Log message: New testcase, courtesy of Brian Gaeke --- Diffs of the changes: From lattner at cs.uiuc.edu Sun Dec 15 11:38:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 11:38:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/CFrontend/2002-12-15-GlobalConstantTest.c Message-ID: <200212151737.LAA19218@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/CFrontend: 2002-12-15-GlobalConstantTest.c added (r1.1) --- Log message: New test to make sure I'm getting constness right --- Diffs of the changes: From lattner at cs.uiuc.edu Sun Dec 15 11:47:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 11:47:00 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/CFrontend/2002-12-15-StructParameters.c Message-ID: <200212151746.LAA20481@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/CFrontend: 2002-12-15-StructParameters.c added (r1.1) --- Log message: New testcase for structure argument problems. --- Diffs of the changes: From lattner at cs.uiuc.edu Sun Dec 15 12:16:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 12:16:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212151815.MAA22960@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.13 -> 1.14 --- Log message: Remove extraneous #includes, perform FIXME --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.13 llvm/lib/CodeGen/RegAllocSimple.cpp:1.14 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.13 Sun Dec 15 02:02:51 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 12:15:24 2002 @@ -9,16 +9,13 @@ #include "llvm/Type.h" #include "llvm/Constants.h" #include "llvm/Pass.h" -#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Target/MachineInstrInfo.h" #include "llvm/Target/MRegisterInfo.h" -#include "llvm/Target/MachineRegInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/InstVisitor.h" #include "Support/Statistic.h" -#include namespace { struct RegAllocSimple : public FunctionPass { @@ -30,8 +27,7 @@ unsigned NumBytesAllocated, ByteAlignment; // Maps SSA Regs => offsets on the stack where these values are stored - // FIXME: change name to VirtReg2OffsetMap - std::map RegMap; + std::map VirtReg2OffsetMap; // Maps SSA Regs => physical regs std::map SSA2PhysRegMap; @@ -95,7 +91,7 @@ } void cleanupAfterFunction() { - RegMap.clear(); + VirtReg2OffsetMap.clear(); SSA2PhysRegMap.clear(); NumBytesAllocated = ByteAlignment; } @@ -131,7 +127,7 @@ unsigned RegAllocSimple::allocateStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *regClass) { - if (RegMap.find(VirtReg) == RegMap.end()) { + if (VirtReg2OffsetMap.find(VirtReg) == VirtReg2OffsetMap.end()) { #if 0 unsigned size = regClass->getDataSize(); unsigned over = NumBytesAllocated - (NumBytesAllocated % ByteAlignment); @@ -139,14 +135,14 @@ // need to pad by (ByteAlignment - over) NumBytesAllocated += ByteAlignment - over; } - RegMap[VirtReg] = NumBytesAllocated; + VirtReg2OffsetMap[VirtReg] = NumBytesAllocated; NumBytesAllocated += size; #endif // FIXME: forcing each arg to take 4 bytes on the stack - RegMap[VirtReg] = NumBytesAllocated; + VirtReg2OffsetMap[VirtReg] = NumBytesAllocated; NumBytesAllocated += ByteAlignment; } - return RegMap[VirtReg]; + return VirtReg2OffsetMap[VirtReg]; } unsigned RegAllocSimple::getFreeReg(unsigned virtualReg) { From lattner at cs.uiuc.edu Sun Dec 15 12:20:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 12:20:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212151819.MAA23642@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.14 -> 1.15 --- Log message: Prune #includes --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.14 llvm/lib/CodeGen/RegAllocSimple.cpp:1.15 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.14 Sun Dec 15 12:15:24 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 12:19:24 2002 @@ -4,18 +4,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Function.h" -#include "llvm/iTerminators.h" -#include "llvm/Type.h" -#include "llvm/Constants.h" -#include "llvm/Pass.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/MachineInstrInfo.h" -#include "llvm/Target/MRegisterInfo.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Support/InstVisitor.h" #include "Support/Statistic.h" +#include namespace { struct RegAllocSimple : public FunctionPass { From lattner at cs.uiuc.edu Sun Dec 15 12:40:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 12:40:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212151839.MAA24846@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.15 -> 1.16 --- Log message: pull inverse reg class mapping into a class that is sharable and out of the target register description classes. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.15 llvm/lib/CodeGen/RegAllocSimple.cpp:1.16 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.15 Sun Dec 15 12:19:24 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 12:38:59 2002 @@ -11,6 +11,30 @@ #include "Support/Statistic.h" #include +/// PhysRegClassMap - Construct a mapping of physical register numbers to their +/// register classes. +/// +/// NOTE: This class will eventually be pulled out to somewhere shared. +/// +class PhysRegClassMap { + std::map PhysReg2RegClassMap; +public: + PhysRegClassMap(const MRegisterInfo *RI) { + for (MRegisterInfo::const_iterator I = RI->regclass_begin(), + E = RI->regclass_end(); I != E; ++I) + for (unsigned i=0; i < (*I)->getNumRegs(); ++i) + PhysReg2RegClassMap[(*I)->getRegister(i)] = *I; + } + + const TargetRegisterClass *operator[](unsigned Reg) { + assert(PhysReg2RegClassMap[Reg] && "Register is not a known physreg!"); + return PhysReg2RegClassMap[Reg]; + } + + const TargetRegisterClass *get(unsigned Reg) { return operator[](Reg); } +}; + + namespace { struct RegAllocSimple : public FunctionPass { TargetMachine &TM; @@ -27,7 +51,7 @@ std::map SSA2PhysRegMap; // Maps physical register to their register classes - std::map PhysReg2RegClassMap; + PhysRegClassMap PhysRegClasses; // Made to combat the incorrect allocation of r2 = add r1, r1 std::map VirtReg2PhysRegMap; @@ -40,11 +64,9 @@ RegAllocSimple(TargetMachine &tm) : TM(tm), CurrMBB(0), maxOffset(0), RegInfo(tm.getRegisterInfo()), - ByteAlignment(4) + ByteAlignment(4), + PhysRegClasses(RegInfo) { - // build reverse mapping for physReg -> register class - RegInfo->buildReg2RegClassMap(PhysReg2RegClassMap); - RegsUsed[RegInfo->getFramePointer()] = 1; RegsUsed[RegInfo->getStackPointer()] = 1; @@ -248,7 +270,7 @@ // Find the register class of the target register: should be the // same as the values we're trying to store there - const TargetRegisterClass* regClass = PhysReg2RegClassMap[physReg]; + const TargetRegisterClass* regClass = PhysRegClasses[physReg]; assert(regClass && "Target register class not found!"); unsigned dataSize = regClass->getDataSize(); From lattner at cs.uiuc.edu Sun Dec 15 12:41:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 12:41:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200212151840.MAA24862@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.8 -> 1.9 --- Log message: * Rename const_regclass_begin/end to just regclass_begin/end * Regclass iterators need an extra level of pointerness to work right * Pull inverse mapping code out of target description files --- Diffs of the changes: Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.8 llvm/include/llvm/Target/MRegisterInfo.h:1.9 --- llvm/include/llvm/Target/MRegisterInfo.h:1.8 Fri Dec 13 03:54:10 2002 +++ llvm/include/llvm/Target/MRegisterInfo.h Sun Dec 15 12:40:01 2002 @@ -10,7 +10,6 @@ #define LLVM_TARGET_MREGISTERINFO_H #include "llvm/CodeGen/MachineBasicBlock.h" -#include #include class Type; @@ -61,15 +60,6 @@ virtual unsigned getDataSize() const { return 0; } - void - buildReg2RegClassMap(std::map& - Reg2RegClassMap) const - { - for (unsigned i=0; i < getNumRegs(); ++i) { - Reg2RegClassMap[getRegister(i)] = this; - } - } - //const std::vector &getRegsInClass(void) { return Regs; } //void getAliases(void); }; @@ -156,23 +146,13 @@ virtual unsigned getStackPointer() const = 0; /// Register class iterators - typedef const TargetRegisterClass* const_iterator; + typedef const TargetRegisterClass** const_iterator; - virtual const_iterator const_regclass_begin() const = 0; - virtual const_iterator const_regclass_end() const = 0; + virtual const_iterator regclass_begin() const = 0; + virtual const_iterator regclass_end() const = 0; virtual unsigned getNumRegClasses() const = 0; virtual const TargetRegisterClass* getRegClassForType(const Type* Ty) const=0; - - virtual void - buildReg2RegClassMap(std::map& - Reg2RegClassMap) const { - for (MRegisterInfo::const_iterator I = const_regclass_begin(), - E = const_regclass_end(); I != E; ++I) { - I->buildReg2RegClassMap(Reg2RegClassMap); - } - } - }; #endif From lattner at cs.uiuc.edu Sun Dec 15 12:41:07 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 12:41:07 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterClasses.cpp X86RegisterInfo.h Message-ID: <200212151840.MAA24877@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterClasses.cpp updated: 1.3 -> 1.4 X86RegisterInfo.h updated: 1.8 -> 1.9 --- Log message: * Simplify TargetRegisterClass implementations * Change regclass iterators to use an extra level of pointers --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterClasses.cpp diff -u llvm/lib/Target/X86/X86RegisterClasses.cpp:1.3 llvm/lib/Target/X86/X86RegisterClasses.cpp:1.4 --- llvm/lib/Target/X86/X86RegisterClasses.cpp:1.3 Fri Dec 13 00:56:29 2002 +++ llvm/lib/Target/X86/X86RegisterClasses.cpp Sun Dec 15 12:40:36 2002 @@ -20,11 +20,7 @@ #include "X86RegisterInfo.def" }; - class X86ByteRegisterClass : public TargetRegisterClass { - protected: - - public: - X86ByteRegisterClass() {} + struct X86ByteRegisterClass : public TargetRegisterClass { unsigned getNumRegs() const { return sizeof(X86ByteRegisterClassRegs)/ sizeof(X86ByteRegisterClassRegs[0]); @@ -35,7 +31,6 @@ } unsigned getDataSize() const { return 1; } - } X86ByteRegisterClassInstance; @@ -48,11 +43,7 @@ #include "X86RegisterInfo.def" }; - class X86ShortRegisterClass : public TargetRegisterClass { - protected: - - public: - X86ShortRegisterClass() {} + struct X86ShortRegisterClass : public TargetRegisterClass { unsigned getNumRegs() const { return sizeof(X86ShortRegisterClassRegs)/ sizeof(X86ShortRegisterClassRegs[0]); } @@ -61,7 +52,6 @@ return X86ShortRegisterClassRegs[idx]; } unsigned getDataSize() const { return 2; } - } X86ShortRegisterClassInstance; // @@ -74,11 +64,7 @@ #include "X86RegisterInfo.def" }; - class X86IntRegisterClass : public TargetRegisterClass { - protected: - - public: - X86IntRegisterClass() {} + struct X86IntRegisterClass : public TargetRegisterClass { unsigned getNumRegs() const { return sizeof(X86IntRegisterClassRegs)/ sizeof(X86IntRegisterClassRegs[0]); } @@ -87,7 +73,6 @@ return X86IntRegisterClassRegs[idx]; } unsigned getDataSize() const { return 4; } - } X86IntRegisterClassInstance; @@ -120,21 +105,19 @@ assert(0 && "Invalid type to getClass!"); return 0; // not reached } - - } } -MRegisterInfo::const_iterator X86RegisterInfo::const_regclass_begin() const { - return X86RegClasses[0]; +MRegisterInfo::const_iterator X86RegisterInfo::regclass_begin() const { + return X86RegClasses; } unsigned X86RegisterInfo::getNumRegClasses() const { return sizeof(X86RegClasses)/sizeof(X86RegClasses[0]); } -MRegisterInfo::const_iterator X86RegisterInfo::const_regclass_end() const { - return (X86RegClasses[0]+getNumRegClasses()); +MRegisterInfo::const_iterator X86RegisterInfo::regclass_end() const { + return X86RegClasses+getNumRegClasses(); } Index: llvm/lib/Target/X86/X86RegisterInfo.h diff -u llvm/lib/Target/X86/X86RegisterInfo.h:1.8 llvm/lib/Target/X86/X86RegisterInfo.h:1.9 --- llvm/lib/Target/X86/X86RegisterInfo.h:1.8 Fri Dec 13 03:54:12 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.h Sun Dec 15 12:40:36 2002 @@ -14,8 +14,8 @@ struct X86RegisterInfo : public MRegisterInfo { X86RegisterInfo(); - MRegisterInfo::const_iterator const_regclass_begin() const; - MRegisterInfo::const_iterator const_regclass_end() const; + MRegisterInfo::const_iterator regclass_begin() const; + MRegisterInfo::const_iterator regclass_end() const; MachineBasicBlock::iterator storeReg2RegOffset(MachineBasicBlock *MBB, From lattner at cs.uiuc.edu Sun Dec 15 13:08:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 13:08:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212151907.NAA25457@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.16 -> 1.17 --- Log message: * Remove some unneccesary instance variables * Make allocateStackSpaceFor only allocate the right amount of space --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.16 llvm/lib/CodeGen/RegAllocSimple.cpp:1.17 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.16 Sun Dec 15 12:38:59 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 13:07:34 2002 @@ -38,11 +38,9 @@ namespace { struct RegAllocSimple : public FunctionPass { TargetMachine &TM; - MachineBasicBlock *CurrMBB; MachineFunction *MF; - unsigned maxOffset; const MRegisterInfo *RegInfo; - unsigned NumBytesAllocated, ByteAlignment; + unsigned NumBytesAllocated; // Maps SSA Regs => offsets on the stack where these values are stored std::map VirtReg2OffsetMap; @@ -62,9 +60,8 @@ std::map RegsUsed; std::map RegClassIdx; - RegAllocSimple(TargetMachine &tm) : TM(tm), CurrMBB(0), maxOffset(0), + RegAllocSimple(TargetMachine &tm) : TM(tm), RegInfo(tm.getRegisterInfo()), - ByteAlignment(4), PhysRegClasses(RegInfo) { RegsUsed[RegInfo->getFramePointer()] = 1; @@ -109,7 +106,7 @@ void cleanupAfterFunction() { VirtReg2OffsetMap.clear(); SSA2PhysRegMap.clear(); - NumBytesAllocated = ByteAlignment; + NumBytesAllocated = 4; /* FIXME: This is X86 specific */ } /// Moves value from memory into that register @@ -144,19 +141,19 @@ const TargetRegisterClass *regClass) { if (VirtReg2OffsetMap.find(VirtReg) == VirtReg2OffsetMap.end()) { -#if 0 - unsigned size = regClass->getDataSize(); - unsigned over = NumBytesAllocated - (NumBytesAllocated % ByteAlignment); - if (size >= ByteAlignment - over) { - // need to pad by (ByteAlignment - over) - NumBytesAllocated += ByteAlignment - over; - } - VirtReg2OffsetMap[VirtReg] = NumBytesAllocated; - NumBytesAllocated += size; -#endif - // FIXME: forcing each arg to take 4 bytes on the stack + unsigned RegSize = regClass->getDataSize(); + + // Align NumBytesAllocated. We should be using TargetData alignment stuff + // to determine this, but we don't know the LLVM type associated with the + // virtual register. Instead, just align to a multiple of the size for now. + NumBytesAllocated += RegSize-1; + NumBytesAllocated = NumBytesAllocated/RegSize*RegSize; + + // Assign the slot... VirtReg2OffsetMap[VirtReg] = NumBytesAllocated; - NumBytesAllocated += ByteAlignment; + + // Reserve the space! + NumBytesAllocated += RegSize; } return VirtReg2OffsetMap[VirtReg]; } @@ -241,7 +238,7 @@ for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; ++MBB) { - CurrMBB = &(*MBB); + MachineBasicBlock *CurrMBB = &(*MBB); // Handle PHI instructions specially: add moves to each pred block while (MBB->front()->getOpcode() == 0) { From lattner at cs.uiuc.edu Sun Dec 15 13:30:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 13:30:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200212151929.NAA27788@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.9 -> 1.10 --- Log message: Simplify TargetRegisterClass a bit, also eliminating virtual function call overhead --- Diffs of the changes: Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.9 llvm/include/llvm/Target/MRegisterInfo.h:1.10 --- llvm/include/llvm/Target/MRegisterInfo.h:1.9 Sun Dec 15 12:40:01 2002 +++ llvm/include/llvm/Target/MRegisterInfo.h Sun Dec 15 13:29:14 2002 @@ -42,25 +42,29 @@ }; class TargetRegisterClass { -protected: - TargetRegisterClass() {} - public: + typedef const unsigned* iterator; + typedef const unsigned* const_iterator; - typedef unsigned* iterator; - typedef unsigned* const_iterator; - - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - - virtual unsigned getNumRegs() const { return 0; } - virtual unsigned getRegister(unsigned idx) const { return 0; } +private: + const unsigned RegSize; // Size of register in bytes + const iterator RegsBegin, RegsEnd; +public: + TargetRegisterClass(unsigned RS, iterator RB, iterator RE) + : RegSize(RS), RegsBegin(RB), RegsEnd(RE) {} + virtual ~TargetRegisterClass() {} // Allow subclasses + + iterator begin() const { return RegsBegin; } + iterator end() const { return RegsEnd; } + + unsigned getNumRegs() const { return RegsEnd-RegsBegin; } + unsigned getRegister(unsigned i) const { + assert(i < getNumRegs() && "Register number out of range!"); + return RegsBegin[i]; + } - virtual unsigned getDataSize() const { return 0; } + unsigned getDataSize() const { return RegSize; } - //const std::vector &getRegsInClass(void) { return Regs; } //void getAliases(void); }; @@ -146,7 +150,7 @@ virtual unsigned getStackPointer() const = 0; /// Register class iterators - typedef const TargetRegisterClass** const_iterator; + typedef const TargetRegisterClass * const * const_iterator; virtual const_iterator regclass_begin() const = 0; virtual const_iterator regclass_end() const = 0; From lattner at cs.uiuc.edu Sun Dec 15 13:30:07 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 13:30:07 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterClasses.cpp Message-ID: <200212151929.NAA27799@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterClasses.cpp updated: 1.4 -> 1.5 --- Log message: Changes to make new TargetRegisterClass interface. --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterClasses.cpp diff -u llvm/lib/Target/X86/X86RegisterClasses.cpp:1.4 llvm/lib/Target/X86/X86RegisterClasses.cpp:1.5 --- llvm/lib/Target/X86/X86RegisterClasses.cpp:1.4 Sun Dec 15 12:40:36 2002 +++ llvm/lib/Target/X86/X86RegisterClasses.cpp Sun Dec 15 13:29:34 2002 @@ -14,97 +14,68 @@ }; namespace { - static const unsigned X86ByteRegisterClassRegs[] = { + const unsigned ByteRegClassRegs[] = { #define R(ENUM, NAME, FLAGS, TSFLAGS) #define R8(ENUM, NAME, FLAGS, TSFLAGS) ENUM, #include "X86RegisterInfo.def" }; - struct X86ByteRegisterClass : public TargetRegisterClass { - unsigned getNumRegs() const { - return sizeof(X86ByteRegisterClassRegs)/ - sizeof(X86ByteRegisterClassRegs[0]); - } - unsigned getRegister(unsigned idx) const { - assert(idx < getNumRegs() && "Index out of bounds!"); - return X86ByteRegisterClassRegs[idx]; - } - - unsigned getDataSize() const { return 1; } - } X86ByteRegisterClassInstance; - + TargetRegisterClass X86ByteRegisterClassInstance(1, ByteRegClassRegs, + ByteRegClassRegs+sizeof(ByteRegClassRegs)/sizeof(ByteRegClassRegs[0])); // // // - static const unsigned X86ShortRegisterClassRegs[] = { + const unsigned ShortRegClassRegs[] = { #define R(ENUM, NAME, FLAGS, TSFLAGS) #define R16(ENUM, NAME, FLAGS, TSFLAGS) ENUM, #include "X86RegisterInfo.def" }; - struct X86ShortRegisterClass : public TargetRegisterClass { - unsigned getNumRegs() const { - return sizeof(X86ShortRegisterClassRegs)/ - sizeof(X86ShortRegisterClassRegs[0]); } - unsigned getRegister(unsigned idx) const { - assert(idx < getNumRegs() && "Index out of bounds!"); - return X86ShortRegisterClassRegs[idx]; - } - unsigned getDataSize() const { return 2; } - } X86ShortRegisterClassInstance; + TargetRegisterClass X86ShortRegisterClassInstance(2, ShortRegClassRegs, + ShortRegClassRegs+sizeof(ShortRegClassRegs)/sizeof(ShortRegClassRegs[0])); // // // - static const unsigned X86IntRegisterClassRegs[] = { + const unsigned IntRegClassRegs[] = { #define R(ENUM, NAME, FLAGS, TSFLAGS) #define R32(ENUM, NAME, FLAGS, TSFLAGS) ENUM, #include "X86RegisterInfo.def" }; - struct X86IntRegisterClass : public TargetRegisterClass { - unsigned getNumRegs() const { - return sizeof(X86IntRegisterClassRegs)/ - sizeof(X86IntRegisterClassRegs[0]); } - unsigned getRegister(unsigned idx) const { - assert(idx < getNumRegs() && "Index out of bounds!"); - return X86IntRegisterClassRegs[idx]; - } - unsigned getDataSize() const { return 4; } - } X86IntRegisterClassInstance; - + TargetRegisterClass X86IntRegisterClassInstance(4, IntRegClassRegs, + IntRegClassRegs+sizeof(IntRegClassRegs)/sizeof(IntRegClassRegs[0])); - static const TargetRegisterClass *X86RegClasses[] = { + const TargetRegisterClass * const X86RegClasses[] = { &X86ByteRegisterClassInstance, &X86ShortRegisterClassInstance, &X86IntRegisterClassInstance }; +} - const TargetRegisterClass* X86RegisterInfo::getRegClassForType(const Type* Ty) - const - { - switch (Ty->getPrimitiveID()) { - case Type::BoolTyID: - case Type::SByteTyID: - case Type::UByteTyID: return &X86ByteRegisterClassInstance; - case Type::ShortTyID: - case Type::UShortTyID: return &X86ShortRegisterClassInstance; - case Type::LongTyID: // None of these are handled yet! - case Type::ULongTyID: // FIXME: Treat these like ints, this is bogus! - - case Type::IntTyID: - case Type::UIntTyID: - case Type::PointerTyID: return &X86IntRegisterClassInstance; - - case Type::FloatTyID: - case Type::DoubleTyID: - - default: - assert(0 && "Invalid type to getClass!"); - return 0; // not reached - } +const TargetRegisterClass* X86RegisterInfo::getRegClassForType(const Type* Ty) + const { + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + case Type::SByteTyID: + case Type::UByteTyID: return &X86ByteRegisterClassInstance; + case Type::ShortTyID: + case Type::UShortTyID: return &X86ShortRegisterClassInstance; + case Type::LongTyID: // None of these are handled yet! + case Type::ULongTyID: // FIXME: Treat these like ints, this is bogus! + + case Type::IntTyID: + case Type::UIntTyID: + case Type::PointerTyID: return &X86IntRegisterClassInstance; + + case Type::FloatTyID: + case Type::DoubleTyID: + + default: + assert(0 && "Invalid type to getClass!"); + return 0; // not reached } } From lattner at cs.uiuc.edu Sun Dec 15 13:52:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 13:52:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212151951.NAA28616@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.17 -> 1.18 --- Log message: * Simplify code a bit by breaking the PHI node handling stuff out into a seperate function from normal regalloc code * Make the regalloc for a block a function instead of part of runOnMachineBB, which makes it easier to see what's going on in runOnMBB. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.17 llvm/lib/CodeGen/RegAllocSimple.cpp:1.18 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.17 Sun Dec 15 13:07:34 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 13:51:14 2002 @@ -60,10 +60,8 @@ std::map RegsUsed; std::map RegClassIdx; - RegAllocSimple(TargetMachine &tm) : TM(tm), - RegInfo(tm.getRegisterInfo()), - PhysRegClasses(RegInfo) - { + RegAllocSimple(TargetMachine &tm) + : TM(tm), RegInfo(tm.getRegisterInfo()), PhysRegClasses(RegInfo) { RegsUsed[RegInfo->getFramePointer()] = 1; RegsUsed[RegInfo->getStackPointer()] = 1; @@ -75,7 +73,8 @@ return RegsUsed.find(Reg) == RegsUsed.end(); } - /// + /// allocateStackSpaceFor - This allocates space for the specified virtual + /// register to be held on the stack. unsigned allocateStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *regClass); @@ -85,7 +84,7 @@ /// Returns all `borrowed' registers back to the free pool void clearAllRegs() { - RegClassIdx.clear(); + RegClassIdx.clear(); } /// Invalidates any references, real or implicit, to physical registers @@ -106,23 +105,23 @@ void cleanupAfterFunction() { VirtReg2OffsetMap.clear(); SSA2PhysRegMap.clear(); - NumBytesAllocated = 4; /* FIXME: This is X86 specific */ + NumBytesAllocated = 4; // FIXME: This is X86 specific } /// Moves value from memory into that register MachineBasicBlock::iterator - moveUseToReg (MachineBasicBlock *MBB, + moveUseToReg (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned VirtReg, unsigned &PhysReg); /// Saves reg value on the stack (maps virtual register to stack value) MachineBasicBlock::iterator - saveVirtRegToStack (MachineBasicBlock *MBB, + saveVirtRegToStack (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned VirtReg, unsigned PhysReg); MachineBasicBlock::iterator - savePhysRegToStack (MachineBasicBlock *MBB, + savePhysRegToStack (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned PhysReg); /// runOnFunction - Top level implementation of instruction selection for @@ -130,6 +129,13 @@ /// bool runOnMachineFunction(MachineFunction &Fn); + /// AllocateBasicBlock - Register allocate the specified basic block. + void AllocateBasicBlock(MachineBasicBlock &MBB); + + /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions + /// in predecessor basic blocks. + void EliminatePHINodes(MachineBasicBlock &MBB); + bool runOnFunction(Function &Fn) { return runOnMachineFunction(MachineFunction::get(&Fn)); } @@ -137,6 +143,8 @@ } +/// allocateStackSpaceFor - This allocates space for the specified virtual +/// register to be held on the stack. unsigned RegAllocSimple::allocateStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *regClass) { @@ -180,7 +188,7 @@ } MachineBasicBlock::iterator -RegAllocSimple::moveUseToReg (MachineBasicBlock *MBB, +RegAllocSimple::moveUseToReg (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned VirtReg, unsigned &PhysReg) { @@ -191,13 +199,13 @@ PhysReg = getFreeReg(VirtReg); // Add move instruction(s) - return RegInfo->loadRegOffset2Reg(MBB, I, PhysReg, + return RegInfo->loadRegOffset2Reg(&MBB, I, PhysReg, RegInfo->getFramePointer(), -stackOffset, regClass->getDataSize()); } MachineBasicBlock::iterator -RegAllocSimple::saveVirtRegToStack (MachineBasicBlock *MBB, +RegAllocSimple::saveVirtRegToStack (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned VirtReg, unsigned PhysReg) { @@ -207,13 +215,13 @@ unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass); // Add move instruction(s) - return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, + return RegInfo->storeReg2RegOffset(&MBB, I, PhysReg, RegInfo->getFramePointer(), -stackOffset, regClass->getDataSize()); } MachineBasicBlock::iterator -RegAllocSimple::savePhysRegToStack (MachineBasicBlock *MBB, +RegAllocSimple::savePhysRegToStack (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned PhysReg) { @@ -223,157 +231,157 @@ unsigned offset = allocateStackSpaceFor(PhysReg, regClass); // Add move instruction(s) - return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, + return RegInfo->storeReg2RegOffset(&MBB, I, PhysReg, RegInfo->getFramePointer(), offset, regClass->getDataSize()); } -bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) { - cleanupAfterFunction(); - - unsigned virtualReg, physReg; - DEBUG(std::cerr << "Machine Function " << "\n"); - MF = &Fn; - - for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); - MBB != MBBe; ++MBB) - { - MachineBasicBlock *CurrMBB = &(*MBB); - - // Handle PHI instructions specially: add moves to each pred block - while (MBB->front()->getOpcode() == 0) { - MachineInstr *MI = MBB->front(); - // get rid of the phi - MBB->erase(MBB->begin()); +/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in +/// predecessor basic blocks. +void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) { + while (MBB.front()->getOpcode() == 0) { + MachineInstr *MI = MBB.front(); + // get rid of the phi + MBB.erase(MBB.begin()); - // a preliminary pass that will invalidate any registers that - // are used by the instruction (including implicit uses) - invalidatePhysRegs(MI); - - DEBUG(std::cerr << "num invalid regs: " << RegsUsed.size() << "\n"); - - DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n"); - MachineOperand &targetReg = MI->getOperand(0); - - // If it's a virtual register, allocate a physical one - // otherwise, just use whatever register is there now - // note: it MUST be a register -- we're assigning to it - virtualReg = (unsigned) targetReg.getAllocatedRegNum(); - if (targetReg.isVirtualRegister()) { - physReg = getFreeReg(virtualReg); - } else { - physReg = virtualReg; - } - - // Find the register class of the target register: should be the - // same as the values we're trying to store there - const TargetRegisterClass* regClass = PhysRegClasses[physReg]; - assert(regClass && "Target register class not found!"); - unsigned dataSize = regClass->getDataSize(); - - for (int i = MI->getNumOperands() - 1; i >= 2; i-=2) { - MachineOperand &opVal = MI->getOperand(i-1); - - // Get the MachineBasicBlock equivalent of the BasicBlock that is the - // source path the phi - MachineBasicBlock *opBlock = MI->getOperand(i).getMachineBasicBlock(); - MachineBasicBlock::iterator opI = opBlock->end(); - MachineInstr *opMI = *(--opI); - const MachineInstrInfo &MII = TM.getInstrInfo(); - // must backtrack over ALL the branches in the previous block, until no more - while ((MII.isBranch(opMI->getOpcode()) || MII.isReturn(opMI->getOpcode())) - && opI != opBlock->begin()) - { - opMI = *(--opI); - } - // move back to the first branch instruction so new instructions - // are inserted right in front of it and not in front of a non-branch - ++opI; - - - // Retrieve the constant value from this op, move it to target - // register of the phi - if (opVal.getType() == MachineOperand::MO_SignExtendedImmed || - opVal.getType() == MachineOperand::MO_UnextendedImmed) - { - opI = RegInfo->moveImm2Reg(opBlock, opI, physReg, - (unsigned) opVal.getImmedValue(), - dataSize); - saveVirtRegToStack(opBlock, opI, virtualReg, physReg); - } else { - // Allocate a physical register and add a move in the BB - unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum(); - unsigned opPhysReg; // = getFreeReg(opVirtualReg); - opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg); - //opI = RegInfo->moveReg2Reg(opBlock, opI, physReg, opPhysReg, - // dataSize); - // Save that register value to the stack of the TARGET REG - saveVirtRegToStack(opBlock, opI, virtualReg, physReg); - } + // a preliminary pass that will invalidate any registers that + // are used by the instruction (including implicit uses) + invalidatePhysRegs(MI); + + DEBUG(std::cerr << "num invalid regs: " << RegsUsed.size() << "\n"); + + DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n"); + MachineOperand &targetReg = MI->getOperand(0); + + // If it's a virtual register, allocate a physical one + // otherwise, just use whatever register is there now + // note: it MUST be a register -- we're assigning to it + unsigned virtualReg = (unsigned) targetReg.getAllocatedRegNum(); + unsigned physReg; + if (targetReg.isVirtualRegister()) { + physReg = getFreeReg(virtualReg); + } else { + physReg = virtualReg; + } + + // Find the register class of the target register: should be the + // same as the values we're trying to store there + const TargetRegisterClass* regClass = PhysRegClasses[physReg]; + assert(regClass && "Target register class not found!"); + unsigned dataSize = regClass->getDataSize(); + + for (int i = MI->getNumOperands() - 1; i >= 2; i-=2) { + MachineOperand &opVal = MI->getOperand(i-1); + + // Get the MachineBasicBlock equivalent of the BasicBlock that is the + // source path the phi + MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock(); + MachineBasicBlock::iterator opI = opBlock.end(); + MachineInstr *opMI = *--opI; + const MachineInstrInfo &MII = TM.getInstrInfo(); - // make regs available to other instructions - clearAllRegs(); + // must backtrack over ALL the branches in the previous block, until no + // more + while (MII.isBranch(opMI->getOpcode()) && opI != opBlock.begin()) + opMI = *--opI; + + // move back to the first branch instruction so new instructions + // are inserted right in front of it and not in front of a non-branch + if (!MII.isBranch(opMI->getOpcode())) + ++opI; + + // Retrieve the constant value from this op, move it to target + // register of the phi + if (opVal.isImmediate()) { + opI = RegInfo->moveImm2Reg(&opBlock, opI, physReg, + (unsigned) opVal.getImmedValue(), + dataSize); + saveVirtRegToStack(opBlock, opI, virtualReg, physReg); + } else { + // Allocate a physical register and add a move in the BB + unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum(); + unsigned opPhysReg; // = getFreeReg(opVirtualReg); + opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg); + //opI = RegInfo->moveReg2Reg(opBlock, opI, physReg, opPhysReg, + // dataSize); + // Save that register value to the stack of the TARGET REG + saveVirtRegToStack(opBlock, opI, virtualReg, physReg); } - // really delete the instruction - delete MI; + // make regs available to other instructions + clearAllRegs(); } + + // really delete the instruction + delete MI; + } +} - //loop over each basic block - for (MachineBasicBlock::iterator I = MBB->begin(); I != MBB->end(); ++I) - { - MachineInstr *MI = *I; - - // a preliminary pass that will invalidate any registers that - // are used by the instruction (including implicit uses) - invalidatePhysRegs(MI); - - // Loop over uses, move from memory into registers - for (int i = MI->getNumOperands() - 1; i >= 0; --i) { - MachineOperand &op = MI->getOperand(i); - - if (op.getType() == MachineOperand::MO_SignExtendedImmed || - op.getType() == MachineOperand::MO_UnextendedImmed) - { - DEBUG(std::cerr << "const\n"); - } else if (op.isVirtualRegister()) { - virtualReg = (unsigned) op.getAllocatedRegNum(); - DEBUG(std::cerr << "op: " << op << "\n"); - DEBUG(std::cerr << "\t inst[" << i << "]: "; - MI->print(std::cerr, TM)); - - // make sure the same virtual register maps to the same physical - // register in any given instruction - if (VirtReg2PhysRegMap.find(virtualReg) != VirtReg2PhysRegMap.end()) { - physReg = VirtReg2PhysRegMap[virtualReg]; - } else { - if (op.opIsDef()) { - if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) { - // must be same register number as the first operand - // This maps a = b + c into b += c, and saves b into a's spot - physReg = (unsigned) MI->getOperand(1).getAllocatedRegNum(); - } else { - physReg = getFreeReg(virtualReg); - } - MachineBasicBlock::iterator J = I; - J = saveVirtRegToStack(CurrMBB, ++J, virtualReg, physReg); - I = --J; + +void RegAllocSimple::AllocateBasicBlock(MachineBasicBlock &MBB) { + // Handle PHI instructions specially: add moves to each pred block + EliminatePHINodes(MBB); + + //loop over each basic block + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { + MachineInstr *MI = *I; + + // a preliminary pass that will invalidate any registers that + // are used by the instruction (including implicit uses) + invalidatePhysRegs(MI); + + // Loop over uses, move from memory into registers + for (int i = MI->getNumOperands() - 1; i >= 0; --i) { + MachineOperand &op = MI->getOperand(i); + + if (op.isImmediate()) { + DEBUG(std::cerr << "const\n"); + } else if (op.isVirtualRegister()) { + unsigned virtualReg = (unsigned) op.getAllocatedRegNum(); + DEBUG(std::cerr << "op: " << op << "\n"); + DEBUG(std::cerr << "\t inst[" << i << "]: "; + MI->print(std::cerr, TM)); + + // make sure the same virtual register maps to the same physical + // register in any given instruction + unsigned physReg; + if (VirtReg2PhysRegMap.find(virtualReg) != VirtReg2PhysRegMap.end()) { + physReg = VirtReg2PhysRegMap[virtualReg]; + } else { + if (op.opIsDef()) { + if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) { + // must be same register number as the first operand + // This maps a = b + c into b += c, and saves b into a's spot + physReg = (unsigned) MI->getOperand(1).getAllocatedRegNum(); } else { - I = moveUseToReg(CurrMBB, I, virtualReg, physReg); + physReg = getFreeReg(virtualReg); } - VirtReg2PhysRegMap[virtualReg] = physReg; + MachineBasicBlock::iterator J = I; + J = saveVirtRegToStack(MBB, ++J, virtualReg, physReg); + I = --J; + } else { + I = moveUseToReg(MBB, I, virtualReg, physReg); } - MI->SetMachineOperandReg(i, physReg); - DEBUG(std::cerr << "virt: " << virtualReg << - ", phys: " << op.getAllocatedRegNum() << "\n"); + VirtReg2PhysRegMap[virtualReg] = physReg; } + MI->SetMachineOperandReg(i, physReg); + DEBUG(std::cerr << "virt: " << virtualReg << + ", phys: " << op.getAllocatedRegNum() << "\n"); } - - clearAllRegs(); - VirtReg2PhysRegMap.clear(); } - + + clearAllRegs(); + VirtReg2PhysRegMap.clear(); } +} + +bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) { + DEBUG(std::cerr << "Machine Function " << "\n"); + MF = &Fn; + + for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); + MBB != MBBe; ++MBB) + AllocateBasicBlock(*MBB); // add prologue we should preserve callee-save registers... MachineFunction::iterator Fi = Fn.begin(); @@ -381,21 +389,22 @@ MachineBasicBlock::iterator MBBi = MBB->begin(); RegInfo->emitPrologue(MBB, MBBi, NumBytesAllocated); + const MachineInstrInfo &MII = TM.getInstrInfo(); + // add epilogue to restore the callee-save registers // loop over the basic block for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); - MBB != MBBe; ++MBB) - { + MBB != MBBe; ++MBB) { // check if last instruction is a RET - MachineBasicBlock::iterator I = (*MBB).end(); - MachineInstr *MI = *(--I); - const MachineInstrInfo &MII = TM.getInstrInfo(); + MachineBasicBlock::iterator I = MBB->end(); + MachineInstr *MI = *--I; if (MII.isReturn(MI->getOpcode())) { // this block has a return instruction, add epilogue RegInfo->emitEpilogue(MBB, I, NumBytesAllocated); } } + cleanupAfterFunction(); return false; // We never modify the LLVM itself. } From lattner at cs.uiuc.edu Sun Dec 15 14:07:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 14:07:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp X86RegisterInfo.h Message-ID: <200212152006.OAA29402@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.13 -> 1.14 X86RegisterInfo.h updated: 1.9 -> 1.10 --- Log message: Simplify interfaces used by regalloc to insert code --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.13 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.14 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.13 Fri Dec 13 06:00:06 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Sun Dec 15 14:06:11 2002 @@ -10,6 +10,7 @@ #include "llvm/Constants.h" #include "llvm/Type.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" // X86Regs - Turn the X86RegisterInfo.def file into a bunch of register // descriptors @@ -35,7 +36,7 @@ } MachineBasicBlock::iterator -X86RegisterInfo::storeReg2RegOffset(MachineBasicBlock *MBB, +X86RegisterInfo::storeReg2RegOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg, unsigned DestReg, unsigned ImmOffset, unsigned dataSize) @@ -44,11 +45,11 @@ static const unsigned Opcode[] = { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32 }; MachineInstr *MI = addRegOffset(BuildMI(Opcode[getIdx(dataSize)], 5), DestReg, ImmOffset).addReg(SrcReg); - return ++(MBB->insert(MBBI, MI)); + return ++MBB.insert(MBBI, MI); } MachineBasicBlock::iterator -X86RegisterInfo::loadRegOffset2Reg(MachineBasicBlock *MBB, +X86RegisterInfo::loadRegOffset2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned SrcReg, unsigned ImmOffset, unsigned dataSize) @@ -57,11 +58,11 @@ static const unsigned Opcode[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32 }; MachineInstr *MI = addRegOffset(BuildMI(Opcode[getIdx(dataSize)], 5) .addReg(DestReg), SrcReg, ImmOffset); - return ++(MBB->insert(MBBI, MI)); + return ++MBB.insert(MBBI, MI); } MachineBasicBlock::iterator -X86RegisterInfo::moveReg2Reg(MachineBasicBlock *MBB, +X86RegisterInfo::moveReg2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned SrcReg, unsigned dataSize) const @@ -69,11 +70,11 @@ static const unsigned Opcode[] = { X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 }; MachineInstr *MI = BuildMI(Opcode[getIdx(dataSize)], 2).addReg(DestReg).addReg(SrcReg); - return ++(MBB->insert(MBBI, MI)); + return ++MBB.insert(MBBI, MI); } MachineBasicBlock::iterator -X86RegisterInfo::moveImm2Reg(MachineBasicBlock *MBB, +X86RegisterInfo::moveImm2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned Imm, unsigned dataSize) const @@ -81,7 +82,7 @@ static const unsigned Opcode[] = { X86::MOVir8, X86::MOVir16, X86::MOVir32 }; MachineInstr *MI = BuildMI(Opcode[getIdx(dataSize)], 2).addReg(DestReg).addReg(Imm); - return ++(MBB->insert(MBBI, MI)); + return ++MBB.insert(MBBI, MI); } @@ -106,55 +107,47 @@ return CallerSaveRegs; } -MachineBasicBlock::iterator -X86RegisterInfo::emitPrologue(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MBBI, - unsigned numBytes) const -{ - MachineInstr *MI; +void X86RegisterInfo::emitPrologue(MachineFunction &MF, + unsigned numBytes) const { + MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB + MachineBasicBlock::iterator MBBI = MBB.begin(); // PUSH ebp - MI = BuildMI (X86::PUSHr32, 1).addReg(X86::EBP); - MBBI = ++(MBB->insert(MBBI, MI)); + MachineInstr *MI = BuildMI (X86::PUSHr32, 1).addReg(X86::EBP); + MBBI = ++MBB.insert(MBBI, MI); // MOV ebp, esp MI = BuildMI (X86::MOVrr32, 2).addReg(X86::EBP).addReg(X86::ESP); - MBBI = ++(MBB->insert(MBBI, MI)); + MBBI = ++MBB.insert(MBBI, MI); // adjust stack pointer MI = BuildMI(X86::SUBri32, 2).addReg(X86::ESP).addZImm(numBytes); - MBBI = ++(MBB->insert(MBBI, MI)); + MBBI = ++MBB.insert(MBBI, MI); // PUSH all callee-save registers const unsigned* regs = getCalleeSaveRegs(); while (*regs) { MI = BuildMI(X86::PUSHr32, 1).addReg(*regs); - MBBI = ++(MBB->insert(MBBI, MI)); + MBBI = ++MBB.insert(MBBI, MI); ++regs; } - - return MBBI; } -MachineBasicBlock::iterator -X86RegisterInfo::emitEpilogue(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MBBI, - unsigned numBytes) const -{ - MachineInstr *MI; +void X86RegisterInfo::emitEpilogue(MachineBasicBlock &MBB, + unsigned numBytes) const { + MachineBasicBlock::iterator MBBI = --MBB.end(); + assert((*MBBI)->getOpcode() == X86::RET && + "Can only insert epilog into returning blocks"); // POP all callee-save registers in REVERSE ORDER static const unsigned regs[] = { X86::EBX, X86::EDI, X86::ESI, MRegisterInfo::NoRegister }; unsigned idx = 0; while (regs[idx]) { - MI = BuildMI(X86::POPr32, 1).addReg(regs[idx++]); - MBBI = ++(MBB->insert(MBBI, MI)); + MachineInstr *MI = BuildMI(X86::POPr32, 1).addReg(regs[idx++]); + MBBI = ++(MBB.insert(MBBI, MI)); } // insert LEAVE - MI = BuildMI(X86::LEAVE, 0); - MBBI = ++(MBB->insert(MBBI, MI)); - - return MBBI; + MBB.insert(MBBI, BuildMI(X86::LEAVE, 0)); } Index: llvm/lib/Target/X86/X86RegisterInfo.h diff -u llvm/lib/Target/X86/X86RegisterInfo.h:1.9 llvm/lib/Target/X86/X86RegisterInfo.h:1.10 --- llvm/lib/Target/X86/X86RegisterInfo.h:1.9 Sun Dec 15 12:40:36 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.h Sun Dec 15 14:06:11 2002 @@ -18,24 +18,24 @@ MRegisterInfo::const_iterator regclass_end() const; MachineBasicBlock::iterator - storeReg2RegOffset(MachineBasicBlock *MBB, + storeReg2RegOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned SrcReg, unsigned ImmOffset, unsigned dataSize) const; MachineBasicBlock::iterator - loadRegOffset2Reg(MachineBasicBlock *MBB, + loadRegOffset2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned SrcReg, unsigned ImmOffset, unsigned dataSize) const; MachineBasicBlock::iterator - moveReg2Reg(MachineBasicBlock *MBB, + moveReg2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned SrcReg, unsigned dataSize) const; MachineBasicBlock::iterator - moveImm2Reg(MachineBasicBlock *MBB, + moveImm2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned Imm, unsigned dataSize) const; @@ -45,13 +45,8 @@ const unsigned* getCalleeSaveRegs() const; const unsigned* getCallerSaveRegs() const; - MachineBasicBlock::iterator emitPrologue(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MBBI, - unsigned numBytes) const; - - MachineBasicBlock::iterator emitEpilogue(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MBBI, - unsigned numBytes) const; + void emitPrologue(MachineFunction &MF, unsigned numBytes) const; + void emitEpilogue(MachineBasicBlock &MBB, unsigned numBytes) const; /// Returns register class appropriate for input SSA register /// From lattner at cs.uiuc.edu Sun Dec 15 14:07:08 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 14:07:08 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200212152006.OAA29416@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.10 -> 1.11 --- Log message: Simplify interfaces used by regalloc to insert code --- Diffs of the changes: Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.10 llvm/include/llvm/Target/MRegisterInfo.h:1.11 --- llvm/include/llvm/Target/MRegisterInfo.h:1.10 Sun Dec 15 13:29:14 2002 +++ llvm/include/llvm/Target/MRegisterInfo.h Sun Dec 15 14:06:25 2002 @@ -13,6 +13,7 @@ #include class Type; +class MachineFunction; /// MRegisterDesc - This record contains all of the information known about a /// particular register. @@ -112,36 +113,32 @@ virtual MachineBasicBlock::iterator - storeReg2RegOffset(MachineBasicBlock *MBB, + storeReg2RegOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg, unsigned DestReg, unsigned ImmOffset, unsigned dataSize) const = 0; virtual MachineBasicBlock::iterator - loadRegOffset2Reg(MachineBasicBlock *MBB, + loadRegOffset2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned SrcReg, unsigned ImmOffset, unsigned dataSize) const = 0; virtual MachineBasicBlock::iterator - moveReg2Reg(MachineBasicBlock *MBB, + moveReg2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned SrcReg, unsigned dataSize) const = 0; virtual MachineBasicBlock::iterator - moveImm2Reg(MachineBasicBlock *MBB, + moveImm2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned Imm, unsigned dataSize) const = 0; - virtual MachineBasicBlock::iterator - emitPrologue(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MBBI, - unsigned numBytes) const = 0; + virtual void + emitPrologue(MachineFunction &MF, unsigned numBytes) const = 0; - virtual MachineBasicBlock::iterator - emitEpilogue(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MBBI, - unsigned numBytes) const = 0; + virtual void + emitEpilogue(MachineBasicBlock &MBB, unsigned numBytes) const = 0; virtual const unsigned* getCalleeSaveRegs() const = 0; virtual const unsigned* getCallerSaveRegs() const = 0; From lattner at cs.uiuc.edu Sun Dec 15 14:07:15 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 14:07:15 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152006.OAA29425@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.18 -> 1.19 --- Log message: Simplify interfaces used by regalloc to insert code --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.18 llvm/lib/CodeGen/RegAllocSimple.cpp:1.19 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.18 Sun Dec 15 13:51:14 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 14:06:35 2002 @@ -199,7 +199,7 @@ PhysReg = getFreeReg(VirtReg); // Add move instruction(s) - return RegInfo->loadRegOffset2Reg(&MBB, I, PhysReg, + return RegInfo->loadRegOffset2Reg(MBB, I, PhysReg, RegInfo->getFramePointer(), -stackOffset, regClass->getDataSize()); } @@ -215,7 +215,7 @@ unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass); // Add move instruction(s) - return RegInfo->storeReg2RegOffset(&MBB, I, PhysReg, + return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(), -stackOffset, regClass->getDataSize()); } @@ -231,7 +231,7 @@ unsigned offset = allocateStackSpaceFor(PhysReg, regClass); // Add move instruction(s) - return RegInfo->storeReg2RegOffset(&MBB, I, PhysReg, + return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(), offset, regClass->getDataSize()); } @@ -293,7 +293,7 @@ // Retrieve the constant value from this op, move it to target // register of the phi if (opVal.isImmediate()) { - opI = RegInfo->moveImm2Reg(&opBlock, opI, physReg, + opI = RegInfo->moveImm2Reg(opBlock, opI, physReg, (unsigned) opVal.getImmedValue(), dataSize); saveVirtRegToStack(opBlock, opI, virtualReg, physReg); @@ -384,10 +384,7 @@ AllocateBasicBlock(*MBB); // add prologue we should preserve callee-save registers... - MachineFunction::iterator Fi = Fn.begin(); - MachineBasicBlock *MBB = Fi; - MachineBasicBlock::iterator MBBi = MBB->begin(); - RegInfo->emitPrologue(MBB, MBBi, NumBytesAllocated); + RegInfo->emitPrologue(Fn, NumBytesAllocated); const MachineInstrInfo &MII = TM.getInstrInfo(); @@ -400,7 +397,7 @@ MachineInstr *MI = *--I; if (MII.isReturn(MI->getOpcode())) { // this block has a return instruction, add epilogue - RegInfo->emitEpilogue(MBB, I, NumBytesAllocated); + RegInfo->emitEpilogue(*MBB, NumBytesAllocated); } } From lattner at cs.uiuc.edu Sun Dec 15 14:36:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 14:36:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/MachineFunction.cpp MachineInstr.cpp Message-ID: <200212152035.OAA30261@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: MachineFunction.cpp updated: 1.30 -> 1.31 MachineInstr.cpp updated: 1.65 -> 1.66 --- Log message: Implement printing of MBB arguments --- Diffs of the changes: Index: llvm/lib/CodeGen/MachineFunction.cpp diff -u llvm/lib/CodeGen/MachineFunction.cpp:1.30 llvm/lib/CodeGen/MachineFunction.cpp:1.31 --- llvm/lib/CodeGen/MachineFunction.cpp:1.30 Wed Nov 20 12:55:27 2002 +++ llvm/lib/CodeGen/MachineFunction.cpp Sun Dec 15 14:35:25 2002 @@ -112,8 +112,7 @@ for (const_iterator BB = begin(); BB != end(); ++BB) { BasicBlock *LBB = BB->getBasicBlock(); - OS << "\n" << LBB->getName() << " (" - << (const void*)BB->getBasicBlock() << "):\n"; + OS << "\n" << LBB->getName() << " (" << (const void*)LBB << "):\n"; for (MachineBasicBlock::const_iterator I = BB->begin(); I != BB->end();++I){ OS << "\t"; (*I)->print(OS, Target); Index: llvm/lib/CodeGen/MachineInstr.cpp diff -u llvm/lib/CodeGen/MachineInstr.cpp:1.65 llvm/lib/CodeGen/MachineInstr.cpp:1.66 --- llvm/lib/CodeGen/MachineInstr.cpp:1.65 Sun Nov 17 17:22:13 2002 +++ llvm/lib/CodeGen/MachineInstr.cpp Sun Dec 15 14:35:25 2002 @@ -260,6 +260,12 @@ OS << ")"; break; } + case MachineOperand::MO_MachineBasicBlock: + OS << "bb<" + << ((Value*)MO.getMachineBasicBlock()->getBasicBlock())->getName() + << "," << (void*)MO.getMachineBasicBlock()->getBasicBlock() << ">"; + break; + default: assert(0 && "Unrecognized operand type"); } @@ -335,47 +341,47 @@ return os << "\n"; } -std::ostream &operator<<(std::ostream &os, const MachineOperand &mop) +std::ostream &operator<<(std::ostream &os, const MachineOperand &MO) { - if (mop.opHiBits32()) + if (MO.opHiBits32()) os << "%lm("; - else if (mop.opLoBits32()) + else if (MO.opLoBits32()) os << "%lo("; - else if (mop.opHiBits64()) + else if (MO.opHiBits64()) os << "%hh("; - else if (mop.opLoBits64()) + else if (MO.opLoBits64()) os << "%hm("; - switch (mop.getType()) + switch (MO.getType()) { case MachineOperand::MO_VirtualRegister: os << "%reg"; - OutputValue(os, mop.getVRegValue()); - if (mop.hasAllocatedReg()) { + OutputValue(os, MO.getVRegValue()); + if (MO.hasAllocatedReg()) { os << "=="; - OutputReg(os, mop.getAllocatedRegNum()); + OutputReg(os, MO.getAllocatedRegNum()); } break; case MachineOperand::MO_CCRegister: os << "%ccreg"; - OutputValue(os, mop.getVRegValue()); - if (mop.hasAllocatedReg()) { + OutputValue(os, MO.getVRegValue()); + if (MO.hasAllocatedReg()) { os << "=="; - OutputReg(os, mop.getAllocatedRegNum()); + OutputReg(os, MO.getAllocatedRegNum()); } break; case MachineOperand::MO_MachineRegister: - OutputReg(os, mop.getMachineRegNum()); + OutputReg(os, MO.getMachineRegNum()); break; case MachineOperand::MO_SignExtendedImmed: - os << (long)mop.getImmedValue(); + os << (long)MO.getImmedValue(); break; case MachineOperand::MO_UnextendedImmed: - os << (long)mop.getImmedValue(); + os << (long)MO.getImmedValue(); break; case MachineOperand::MO_PCRelativeDisp: { - const Value* opVal = mop.getVRegValue(); + const Value* opVal = MO.getVRegValue(); bool isLabel = isa(opVal) || isa(opVal); os << "%disp(" << (isLabel? "label " : "addr-of-val "); if (opVal->hasName()) @@ -385,12 +391,17 @@ os << ")"; break; } + case MachineOperand::MO_MachineBasicBlock: + os << "bb<" + << ((Value*)MO.getMachineBasicBlock()->getBasicBlock())->getName() + << "," << (void*)MO.getMachineBasicBlock()->getBasicBlock() << ">"; + break; default: assert(0 && "Unrecognized operand type"); break; } - if (mop.flags & + if (MO.flags & (MachineOperand::HIFLAG32 | MachineOperand::LOFLAG32 | MachineOperand::HIFLAG64 | MachineOperand::LOFLAG64)) os << ")"; From lattner at cs.uiuc.edu Sun Dec 15 14:37:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 14:37:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152036.OAA30274@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.19 -> 1.20 --- Log message: Grab bag of minor cleanups. Export some statistics about the number of spills and reloads emitted --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.19 llvm/lib/CodeGen/RegAllocSimple.cpp:1.20 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.19 Sun Dec 15 14:06:35 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 14:36:09 2002 @@ -10,6 +10,7 @@ #include "llvm/Target/TargetMachine.h" #include "Support/Statistic.h" #include +#include /// PhysRegClassMap - Construct a mapping of physical register numbers to their /// register classes. @@ -36,7 +37,10 @@ namespace { - struct RegAllocSimple : public FunctionPass { + Statistic<> NumSpilled ("ra-simple", "Number of registers spilled"); + Statistic<> NumReloaded("ra-simple", "Number of registers reloaded"); + + class RegAllocSimple : public FunctionPass { TargetMachine &TM; MachineFunction *MF; const MRegisterInfo *RegInfo; @@ -54,20 +58,40 @@ // Made to combat the incorrect allocation of r2 = add r1, r1 std::map VirtReg2PhysRegMap; - // Maps RegClass => which index we can take a register from. Since this is a - // simple register allocator, when we need a register of a certain class, we - // just take the next available one. - std::map RegsUsed; + // RegsUsed - Keep track of what registers are currently in use. + std::set RegsUsed; + + // RegClassIdx - Maps RegClass => which index we can take a register + // from. Since this is a simple register allocator, when we need a register + // of a certain class, we just take the next available one. std::map RegClassIdx; + public: + RegAllocSimple(TargetMachine &tm) : TM(tm), RegInfo(tm.getRegisterInfo()), PhysRegClasses(RegInfo) { - RegsUsed[RegInfo->getFramePointer()] = 1; - RegsUsed[RegInfo->getStackPointer()] = 1; + RegsUsed.insert(RegInfo->getFramePointer()); + RegsUsed.insert(RegInfo->getStackPointer()); cleanupAfterFunction(); } + bool runOnFunction(Function &Fn) { + return runOnMachineFunction(MachineFunction::get(&Fn)); + } + + private: + /// runOnMachineFunction - Register allocate the whole function + bool runOnMachineFunction(MachineFunction &Fn); + + /// AllocateBasicBlock - Register allocate the specified basic block. + void AllocateBasicBlock(MachineBasicBlock &MBB); + + /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions + /// in predecessor basic blocks. + void EliminatePHINodes(MachineBasicBlock &MBB); + + bool isAvailableReg(unsigned Reg) { // assert(Reg < MRegisterInfo::FirstVirtualReg && "..."); return RegsUsed.find(Reg) == RegsUsed.end(); @@ -78,8 +102,11 @@ unsigned allocateStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *regClass); - /// Given size (in bytes), returns a register that is currently unused + /// Given a virtual register, returns a physical register that is currently + /// unused. + /// /// Side effect: marks that register as being used until manually cleared + /// unsigned getFreeReg(unsigned virtualReg); /// Returns all `borrowed' registers back to the free pool @@ -91,15 +118,14 @@ /// void invalidatePhysRegs(const MachineInstr *MI) { unsigned Opcode = MI->getOpcode(); - const MachineInstrInfo &MII = TM.getInstrInfo(); - const MachineInstrDescriptor &Desc = MII.get(Opcode); + const MachineInstrDescriptor &Desc = TM.getInstrInfo().get(Opcode); const unsigned *regs = Desc.ImplicitUses; while (*regs) - RegsUsed[*regs++] = 1; + RegsUsed.insert(*regs++); regs = Desc.ImplicitDefs; while (*regs) - RegsUsed[*regs++] = 1; + RegsUsed.insert(*regs++); } void cleanupAfterFunction() { @@ -123,22 +149,6 @@ MachineBasicBlock::iterator savePhysRegToStack (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned PhysReg); - - /// runOnFunction - Top level implementation of instruction selection for - /// the entire function. - /// - bool runOnMachineFunction(MachineFunction &Fn); - - /// AllocateBasicBlock - Register allocate the specified basic block. - void AllocateBasicBlock(MachineBasicBlock &MBB); - - /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions - /// in predecessor basic blocks. - void EliminatePHINodes(MachineBasicBlock &MBB); - - bool runOnFunction(Function &Fn) { - return runOnMachineFunction(MachineFunction::get(&Fn)); - } }; } @@ -182,9 +192,8 @@ if (isAvailableReg(physReg)) return physReg; - else { + else return getFreeReg(virtualReg); - } } MachineBasicBlock::iterator @@ -199,6 +208,7 @@ PhysReg = getFreeReg(VirtReg); // Add move instruction(s) + ++NumReloaded; return RegInfo->loadRegOffset2Reg(MBB, I, PhysReg, RegInfo->getFramePointer(), -stackOffset, regClass->getDataSize()); @@ -215,6 +225,7 @@ unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass); // Add move instruction(s) + ++NumSpilled; return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(), -stackOffset, regClass->getDataSize()); @@ -231,6 +242,7 @@ unsigned offset = allocateStackSpaceFor(PhysReg, regClass); // Add move instruction(s) + ++NumSpilled; return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(), offset, regClass->getDataSize()); @@ -239,9 +251,11 @@ /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in /// predecessor basic blocks. void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) { + const MachineInstrInfo &MII = TM.getInstrInfo(); + while (MBB.front()->getOpcode() == 0) { MachineInstr *MI = MBB.front(); - // get rid of the phi + // Unlink the PHI node from the basic block... but don't delete the PHI MBB.erase(MBB.begin()); // a preliminary pass that will invalidate any registers that @@ -249,13 +263,13 @@ invalidatePhysRegs(MI); DEBUG(std::cerr << "num invalid regs: " << RegsUsed.size() << "\n"); - DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n"); MachineOperand &targetReg = MI->getOperand(0); - // If it's a virtual register, allocate a physical one - // otherwise, just use whatever register is there now - // note: it MUST be a register -- we're assigning to it + // If it's a virtual register, allocate a physical one otherwise, just use + // whatever register is there now note: it MUST be a register -- we're + // assigning to it! + // unsigned virtualReg = (unsigned) targetReg.getAllocatedRegNum(); unsigned physReg; if (targetReg.isVirtualRegister()) { @@ -278,7 +292,6 @@ MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock(); MachineBasicBlock::iterator opI = opBlock.end(); MachineInstr *opMI = *--opI; - const MachineInstrInfo &MII = TM.getInstrInfo(); // must backtrack over ALL the branches in the previous block, until no // more @@ -300,10 +313,9 @@ } else { // Allocate a physical register and add a move in the BB unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum(); - unsigned opPhysReg; // = getFreeReg(opVirtualReg); + unsigned opPhysReg; opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg); - //opI = RegInfo->moveReg2Reg(opBlock, opI, physReg, opPhysReg, - // dataSize); + // Save that register value to the stack of the TARGET REG saveVirtRegToStack(opBlock, opI, virtualReg, physReg); } @@ -334,9 +346,7 @@ for (int i = MI->getNumOperands() - 1; i >= 0; --i) { MachineOperand &op = MI->getOperand(i); - if (op.isImmediate()) { - DEBUG(std::cerr << "const\n"); - } else if (op.isVirtualRegister()) { + if (op.isVirtualRegister()) { unsigned virtualReg = (unsigned) op.getAllocatedRegNum(); DEBUG(std::cerr << "op: " << op << "\n"); DEBUG(std::cerr << "\t inst[" << i << "]: "; @@ -352,7 +362,7 @@ if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) { // must be same register number as the first operand // This maps a = b + c into b += c, and saves b into a's spot - physReg = (unsigned) MI->getOperand(1).getAllocatedRegNum(); + physReg = MI->getOperand(1).getAllocatedRegNum(); } else { physReg = getFreeReg(virtualReg); } @@ -375,6 +385,8 @@ } } +/// runOnMachineFunction - Register allocate the whole function +/// bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) { DEBUG(std::cerr << "Machine Function " << "\n"); MF = &Fn; @@ -393,9 +405,7 @@ for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; ++MBB) { // check if last instruction is a RET - MachineBasicBlock::iterator I = MBB->end(); - MachineInstr *MI = *--I; - if (MII.isReturn(MI->getOpcode())) { + if (MII.isReturn(MBB->back()->getOpcode())) { // this block has a return instruction, add epilogue RegInfo->emitEpilogue(*MBB, NumBytesAllocated); } From lattner at cs.uiuc.edu Sun Dec 15 14:49:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 14:49:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152048.OAA30483@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.20 -> 1.21 --- Log message: Fix a problem that occurs when PHI nodes have multiple entries for the same predecessor --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.20 llvm/lib/CodeGen/RegAllocSimple.cpp:1.21 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.20 Sun Dec 15 14:36:09 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 14:48:03 2002 @@ -283,43 +283,60 @@ const TargetRegisterClass* regClass = PhysRegClasses[physReg]; assert(regClass && "Target register class not found!"); unsigned dataSize = regClass->getDataSize(); - + for (int i = MI->getNumOperands() - 1; i >= 2; i-=2) { MachineOperand &opVal = MI->getOperand(i-1); // Get the MachineBasicBlock equivalent of the BasicBlock that is the // source path the phi MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock(); - MachineBasicBlock::iterator opI = opBlock.end(); - MachineInstr *opMI = *--opI; - - // must backtrack over ALL the branches in the previous block, until no - // more - while (MII.isBranch(opMI->getOpcode()) && opI != opBlock.begin()) - opMI = *--opI; - // move back to the first branch instruction so new instructions - // are inserted right in front of it and not in front of a non-branch - if (!MII.isBranch(opMI->getOpcode())) - ++opI; - - // Retrieve the constant value from this op, move it to target - // register of the phi - if (opVal.isImmediate()) { - opI = RegInfo->moveImm2Reg(opBlock, opI, physReg, - (unsigned) opVal.getImmedValue(), - dataSize); - saveVirtRegToStack(opBlock, opI, virtualReg, physReg); - } else { - // Allocate a physical register and add a move in the BB - unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum(); - unsigned opPhysReg; - opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg); + // Check to make sure we haven't already emitted the copy for this block. + // This can happen because PHI nodes may have multiple entries for the + // same basic block. It doesn't matter which entry we use though, because + // all incoming values are guaranteed to be the same for a particular bb. + // + // Note that this is N^2 in the number of phi node entries, but since the + // # of entries is tiny, this is not a problem. + // + bool HaveNotEmitted = true; + for (int op = MI->getNumOperands() - 1; op != i; op -= 2) + if (&opBlock == MI->getOperand(op).getMachineBasicBlock()) { + HaveNotEmitted = false; + break; + } - // Save that register value to the stack of the TARGET REG - saveVirtRegToStack(opBlock, opI, virtualReg, physReg); + if (HaveNotEmitted) { + MachineBasicBlock::iterator opI = opBlock.end(); + MachineInstr *opMI = *--opI; + + // must backtrack over ALL the branches in the previous block + while (MII.isBranch(opMI->getOpcode()) && opI != opBlock.begin()) + opMI = *--opI; + + // move back to the first branch instruction so new instructions + // are inserted right in front of it and not in front of a non-branch + if (!MII.isBranch(opMI->getOpcode())) + ++opI; + + // Retrieve the constant value from this op, move it to target + // register of the phi + if (opVal.isImmediate()) { + opI = RegInfo->moveImm2Reg(opBlock, opI, physReg, + (unsigned) opVal.getImmedValue(), + dataSize); + saveVirtRegToStack(opBlock, opI, virtualReg, physReg); + } else { + // Allocate a physical register and add a move in the BB + unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum(); + unsigned opPhysReg; + opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg); + + // Save that register value to the stack of the TARGET REG + saveVirtRegToStack(opBlock, opI, virtualReg, physReg); + } } - + // make regs available to other instructions clearAllRegs(); } From lattner at cs.uiuc.edu Sun Dec 15 14:53:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 14:53:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-phi.ll Message-ID: <200212152052.OAA30615@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-phi.ll updated: 1.3 -> 1.4 --- Log message: Add new testcase for repeated preds --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-phi.ll diff -u llvm/test/Regression/Jello/test-phi.ll:1.3 llvm/test/Regression/Jello/test-phi.ll:1.4 --- llvm/test/Regression/Jello/test-phi.ll:1.3 Fri Dec 13 04:13:45 2002 +++ llvm/test/Regression/Jello/test-phi.ll Sun Dec 15 14:52:08 2002 @@ -11,11 +11,18 @@ br label %T } +int %test(bool %C) { + br bool %C, label %T, label %T +T: + %X = phi int [123, %0], [123, %0] + ret int %X +} + int %main() { br label %Test Test: - %X = phi int [7, %0], [%Y, %Dead] - ret int 0 + %X = phi int [0, %0], [%Y, %Dead] + ret int %X Dead: %Y = shr int 12, ubyte 4 br label %Test From lattner at cs.uiuc.edu Sun Dec 15 15:03:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 15:03:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152102.PAA30881@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.21 -> 1.22 --- Log message: Add a big assert making sure 2 address instructions are formed right --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.21 llvm/lib/CodeGen/RegAllocSimple.cpp:1.22 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.21 Sun Dec 15 14:48:03 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 15:02:20 2002 @@ -379,6 +379,12 @@ if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) { // must be same register number as the first operand // This maps a = b + c into b += c, and saves b into a's spot + assert(MI->getOperand(1).isRegister() && + MI->getOperand(1).getAllocatedRegNum() && + MF->getRegClass(virtualReg) == + PhysRegClasses[MI->getOperand(1).getAllocatedRegNum()] && + "Two address instruction invalid!"); + physReg = MI->getOperand(1).getAllocatedRegNum(); } else { physReg = getFreeReg(virtualReg); From lattner at cs.uiuc.edu Sun Dec 15 15:14:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 15:14:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152113.PAA31251@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.22 -> 1.23 --- Log message: Give simple reg allocator a nice Pass Name --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.22 llvm/lib/CodeGen/RegAllocSimple.cpp:1.23 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.22 Sun Dec 15 15:02:20 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 15:13:12 2002 @@ -80,6 +80,10 @@ return runOnMachineFunction(MachineFunction::get(&Fn)); } + virtual const char *getPassName() const { + return "Simple Register Allocator"; + } + private: /// runOnMachineFunction - Register allocate the whole function bool runOnMachineFunction(MachineFunction &Fn); @@ -328,7 +332,7 @@ saveVirtRegToStack(opBlock, opI, virtualReg, physReg); } else { // Allocate a physical register and add a move in the BB - unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum(); + unsigned opVirtualReg = opVal.getAllocatedRegNum(); unsigned opPhysReg; opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg); From lattner at cs.uiuc.edu Sun Dec 15 15:14:07 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 15:14:07 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp MachineCodeEmitter.cpp Printer.cpp Message-ID: <200212152113.PAA31269@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.69 -> 1.70 MachineCodeEmitter.cpp updated: 1.12 -> 1.13 Printer.cpp updated: 1.28 -> 1.29 --- Log message: Give passes nice names! --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.69 llvm/lib/Target/X86/InstSelectSimple.cpp:1.70 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.69 Sun Dec 15 02:02:15 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Sun Dec 15 15:13:40 2002 @@ -91,6 +91,10 @@ return false; // We never modify the LLVM itself. } + virtual const char *getPassName() const { + return "X86 Simple Instruction Selection"; + } + /// visitBasicBlock - This method is called when we are visiting a new basic /// block. This simply creates a new MachineBasicBlock to emit code into /// and adds it to the current MachineFunction. Subsequent visit* for Index: llvm/lib/Target/X86/MachineCodeEmitter.cpp diff -u llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.12 llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.13 --- llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.12 Sun Dec 15 02:01:39 2002 +++ llvm/lib/Target/X86/MachineCodeEmitter.cpp Sun Dec 15 15:13:40 2002 @@ -25,6 +25,10 @@ bool runOnFunction(Function &F); + virtual const char *getPassName() const { + return "X86 Machine Code Emitter"; + } + private: void emitBasicBlock(MachineBasicBlock &MBB); void emitInstruction(MachineInstr &MI); Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.28 llvm/lib/Target/X86/Printer.cpp:1.29 --- llvm/lib/Target/X86/Printer.cpp:1.28 Sun Dec 15 02:01:39 2002 +++ llvm/lib/Target/X86/Printer.cpp Sun Dec 15 15:13:40 2002 @@ -21,6 +21,10 @@ Printer(TargetMachine &tm, std::ostream &o) : TM(tm), O(o) {} + virtual const char *getPassName() const { + return "X86 Assembly Printer"; + } + bool runOnFunction(Function &F); }; } From lattner at cs.uiuc.edu Sun Dec 15 15:25:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 15:25:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152124.PAA31595@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.23 -> 1.24 --- Log message: Localize a map, remove another --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.23 llvm/lib/CodeGen/RegAllocSimple.cpp:1.24 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.23 Sun Dec 15 15:13:12 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 15:24:30 2002 @@ -49,15 +49,9 @@ // Maps SSA Regs => offsets on the stack where these values are stored std::map VirtReg2OffsetMap; - // Maps SSA Regs => physical regs - std::map SSA2PhysRegMap; - // Maps physical register to their register classes PhysRegClassMap PhysRegClasses; - // Made to combat the incorrect allocation of r2 = add r1, r1 - std::map VirtReg2PhysRegMap; - // RegsUsed - Keep track of what registers are currently in use. std::set RegsUsed; @@ -134,7 +128,6 @@ void cleanupAfterFunction() { VirtReg2OffsetMap.clear(); - SSA2PhysRegMap.clear(); NumBytesAllocated = 4; // FIXME: This is X86 specific } @@ -357,6 +350,9 @@ //loop over each basic block for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { + // Made to combat the incorrect allocation of r2 = add r1, r1 + std::map VirtReg2PhysRegMap; + MachineInstr *MI = *I; // a preliminary pass that will invalidate any registers that @@ -406,9 +402,7 @@ ", phys: " << op.getAllocatedRegNum() << "\n"); } } - clearAllRegs(); - VirtReg2PhysRegMap.clear(); } } From lattner at cs.uiuc.edu Sun Dec 15 15:35:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 15:35:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152134.PAA31873@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.24 -> 1.25 --- Log message: Remove unused savePhysRegToStack method --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.24 llvm/lib/CodeGen/RegAllocSimple.cpp:1.25 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.24 Sun Dec 15 15:24:30 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 15:33:51 2002 @@ -142,10 +142,6 @@ saveVirtRegToStack (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned VirtReg, unsigned PhysReg); - - MachineBasicBlock::iterator - savePhysRegToStack (MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, unsigned PhysReg); }; } @@ -199,8 +195,6 @@ unsigned VirtReg, unsigned &PhysReg) { const TargetRegisterClass* regClass = MF->getRegClass(VirtReg); - assert(regClass); - unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass); PhysReg = getFreeReg(VirtReg); @@ -217,8 +211,6 @@ unsigned VirtReg, unsigned PhysReg) { const TargetRegisterClass* regClass = MF->getRegClass(VirtReg); - assert(regClass); - unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass); // Add move instruction(s) @@ -228,22 +220,6 @@ -stackOffset, regClass->getDataSize()); } -MachineBasicBlock::iterator -RegAllocSimple::savePhysRegToStack (MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned PhysReg) -{ - const TargetRegisterClass* regClass = MF->getRegClass(PhysReg); - assert(regClass); - - unsigned offset = allocateStackSpaceFor(PhysReg, regClass); - - // Add move instruction(s) - ++NumSpilled; - return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, - RegInfo->getFramePointer(), - offset, regClass->getDataSize()); -} /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in /// predecessor basic blocks. @@ -322,16 +298,16 @@ opI = RegInfo->moveImm2Reg(opBlock, opI, physReg, (unsigned) opVal.getImmedValue(), dataSize); - saveVirtRegToStack(opBlock, opI, virtualReg, physReg); } else { // Allocate a physical register and add a move in the BB unsigned opVirtualReg = opVal.getAllocatedRegNum(); unsigned opPhysReg; opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg); - // Save that register value to the stack of the TARGET REG - saveVirtRegToStack(opBlock, opI, virtualReg, physReg); } + + // Save that register value to the stack of the TARGET REG + saveVirtRegToStack(opBlock, opI, virtualReg, physReg); } // make regs available to other instructions @@ -348,7 +324,7 @@ // Handle PHI instructions specially: add moves to each pred block EliminatePHINodes(MBB); - //loop over each basic block + // loop over each instruction for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { // Made to combat the incorrect allocation of r2 = add r1, r1 std::map VirtReg2PhysRegMap; From lattner at cs.uiuc.edu Sun Dec 15 16:06:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 16:06:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineInstr.h Message-ID: <200212152205.QAA00532@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineInstr.h updated: 1.91 -> 1.92 --- Log message: Add new opIsUse method --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineInstr.h diff -u llvm/include/llvm/CodeGen/MachineInstr.h:1.91 llvm/include/llvm/CodeGen/MachineInstr.h:1.92 --- llvm/include/llvm/CodeGen/MachineInstr.h:1.91 Sun Dec 15 02:01:02 2002 +++ llvm/include/llvm/CodeGen/MachineInstr.h Sun Dec 15 16:05:02 2002 @@ -84,12 +84,14 @@ private: // Bit fields of the flags variable used for different operand properties - static const char DEFFLAG = 0x1; // this is a def of the operand - static const char DEFUSEFLAG = 0x2; // this is both a def and a use - static const char HIFLAG32 = 0x4; // operand is %hi32(value_or_immedVal) - static const char LOFLAG32 = 0x8; // operand is %lo32(value_or_immedVal) + static const char DEFFLAG = 0x01; // this is a def of the operand + static const char DEFUSEFLAG = 0x02; // this is both a def and a use + static const char HIFLAG32 = 0x04; // operand is %hi32(value_or_immedVal) + static const char LOFLAG32 = 0x08; // operand is %lo32(value_or_immedVal) static const char HIFLAG64 = 0x10; // operand is %hi64(value_or_immedVal) static const char LOFLAG64 = 0x20; // operand is %lo64(value_or_immedVal) + + static const char USEDEFMASK = 0x03; private: union { @@ -203,6 +205,7 @@ return MBB; } + bool opIsUse () const { return (flags & USEDEFMASK) == 0; } bool opIsDef () const { return flags & DEFFLAG; } bool opIsDefAndUse () const { return flags & DEFUSEFLAG; } bool opHiBits32 () const { return flags & HIFLAG32; } From lattner at cs.uiuc.edu Sun Dec 15 16:17:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 16:17:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MachineInstrInfo.h Message-ID: <200212152216.QAA01540@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MachineInstrInfo.h updated: 1.37 -> 1.38 --- Log message: Export well known instruction opcodes usable by target independant passes --- Diffs of the changes: Index: llvm/include/llvm/Target/MachineInstrInfo.h diff -u llvm/include/llvm/Target/MachineInstrInfo.h:1.37 llvm/include/llvm/Target/MachineInstrInfo.h:1.38 --- llvm/include/llvm/Target/MachineInstrInfo.h:1.37 Thu Dec 12 17:19:51 2002 +++ llvm/include/llvm/Target/MachineInstrInfo.h Sun Dec 15 16:16:08 2002 @@ -85,6 +85,12 @@ MachineInstrInfo(const MachineInstrDescriptor *desc, unsigned descSize, unsigned numRealOpCodes); virtual ~MachineInstrInfo(); + + // Invariant: All instruction sets use opcode #0 as the PHI instruction and + // opcode #1 as the noop instruction. + enum { + PHI = 0, NOOP = 1 + }; unsigned getNumRealOpCodes() const { return numRealOpCodes; } unsigned getNumTotalOpCodes() const { return descSize; } From lattner at cs.uiuc.edu Sun Dec 15 16:20:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 16:20:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152219.QAA01729@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.25 -> 1.26 --- Log message: Variety of small or trivial simplifications to the code, completely eliminated the dependence on PhysRegClassMap --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.25 llvm/lib/CodeGen/RegAllocSimple.cpp:1.26 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.25 Sun Dec 15 15:33:51 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 16:19:19 2002 @@ -12,6 +12,7 @@ #include #include +#if 0 /// PhysRegClassMap - Construct a mapping of physical register numbers to their /// register classes. /// @@ -34,6 +35,7 @@ const TargetRegisterClass *get(unsigned Reg) { return operator[](Reg); } }; +#endif namespace { @@ -49,9 +51,6 @@ // Maps SSA Regs => offsets on the stack where these values are stored std::map VirtReg2OffsetMap; - // Maps physical register to their register classes - PhysRegClassMap PhysRegClasses; - // RegsUsed - Keep track of what registers are currently in use. std::set RegsUsed; @@ -63,7 +62,7 @@ public: RegAllocSimple(TargetMachine &tm) - : TM(tm), RegInfo(tm.getRegisterInfo()), PhysRegClasses(RegInfo) { + : TM(tm), RegInfo(tm.getRegisterInfo()) { RegsUsed.insert(RegInfo->getFramePointer()); RegsUsed.insert(RegInfo->getStackPointer()); @@ -90,18 +89,13 @@ void EliminatePHINodes(MachineBasicBlock &MBB); - bool isAvailableReg(unsigned Reg) { - // assert(Reg < MRegisterInfo::FirstVirtualReg && "..."); - return RegsUsed.find(Reg) == RegsUsed.end(); - } - - /// allocateStackSpaceFor - This allocates space for the specified virtual - /// register to be held on the stack. - unsigned allocateStackSpaceFor(unsigned VirtReg, - const TargetRegisterClass *regClass); + /// getStackSpaceFor - This returns the offset of the specified virtual + /// register on the stack, allocating space if neccesary. + unsigned getStackSpaceFor(unsigned VirtReg, + const TargetRegisterClass *regClass); - /// Given a virtual register, returns a physical register that is currently - /// unused. + /// Given a virtual register, return a compatible physical register that is + /// currently unused. /// /// Side effect: marks that register as being used until manually cleared /// @@ -133,57 +127,52 @@ /// Moves value from memory into that register MachineBasicBlock::iterator - moveUseToReg (MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, unsigned VirtReg, - unsigned &PhysReg); + moveUseToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned VirtReg, unsigned &PhysReg); /// Saves reg value on the stack (maps virtual register to stack value) MachineBasicBlock::iterator - saveVirtRegToStack (MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, unsigned VirtReg, - unsigned PhysReg); + saveVirtRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned VirtReg, unsigned PhysReg); }; } -/// allocateStackSpaceFor - This allocates space for the specified virtual +/// getStackSpaceFor - This allocates space for the specified virtual /// register to be held on the stack. -unsigned RegAllocSimple::allocateStackSpaceFor(unsigned VirtReg, - const TargetRegisterClass *regClass) -{ - if (VirtReg2OffsetMap.find(VirtReg) == VirtReg2OffsetMap.end()) { - unsigned RegSize = regClass->getDataSize(); - - // Align NumBytesAllocated. We should be using TargetData alignment stuff - // to determine this, but we don't know the LLVM type associated with the - // virtual register. Instead, just align to a multiple of the size for now. - NumBytesAllocated += RegSize-1; - NumBytesAllocated = NumBytesAllocated/RegSize*RegSize; - - // Assign the slot... - VirtReg2OffsetMap[VirtReg] = NumBytesAllocated; - - // Reserve the space! - NumBytesAllocated += RegSize; - } - return VirtReg2OffsetMap[VirtReg]; +unsigned RegAllocSimple::getStackSpaceFor(unsigned VirtReg, + const TargetRegisterClass *regClass) { + // Find the location VirtReg would belong... + std::map::iterator I = + VirtReg2OffsetMap.lower_bound(VirtReg); + + if (I != VirtReg2OffsetMap.end() && I->first == VirtReg) + return I->second; // Already has space allocated? + + unsigned RegSize = regClass->getDataSize(); + + // Align NumBytesAllocated. We should be using TargetData alignment stuff + // to determine this, but we don't know the LLVM type associated with the + // virtual register. Instead, just align to a multiple of the size for now. + NumBytesAllocated += RegSize-1; + NumBytesAllocated = NumBytesAllocated/RegSize*RegSize; + + // Assign the slot... + VirtReg2OffsetMap.insert(I, std::make_pair(VirtReg, NumBytesAllocated)); + + // Reserve the space! + NumBytesAllocated += RegSize; + return NumBytesAllocated-RegSize; } unsigned RegAllocSimple::getFreeReg(unsigned virtualReg) { const TargetRegisterClass* regClass = MF->getRegClass(virtualReg); - unsigned physReg; - assert(regClass); - if (RegClassIdx.find(regClass) != RegClassIdx.end()) { - unsigned regIdx = RegClassIdx[regClass]++; - assert(regIdx < regClass->getNumRegs() && "Not enough registers!"); - physReg = regClass->getRegister(regIdx); - } else { - physReg = regClass->getRegister(0); - // assert(physReg < regClass->getNumRegs() && "No registers in class!"); - RegClassIdx[regClass] = 1; - } + + unsigned regIdx = RegClassIdx[regClass]++; + assert(regIdx < regClass->getNumRegs() && "Not enough registers!"); + unsigned physReg = regClass->getRegister(regIdx); - if (isAvailableReg(physReg)) + if (RegsUsed.find(physReg) == RegsUsed.end()) return physReg; else return getFreeReg(virtualReg); @@ -195,7 +184,7 @@ unsigned VirtReg, unsigned &PhysReg) { const TargetRegisterClass* regClass = MF->getRegClass(VirtReg); - unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass); + unsigned stackOffset = getStackSpaceFor(VirtReg, regClass); PhysReg = getFreeReg(VirtReg); // Add move instruction(s) @@ -211,7 +200,7 @@ unsigned VirtReg, unsigned PhysReg) { const TargetRegisterClass* regClass = MF->getRegClass(VirtReg); - unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass); + unsigned stackOffset = getStackSpaceFor(VirtReg, regClass); // Add move instruction(s) ++NumSpilled; @@ -226,34 +215,28 @@ void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) { const MachineInstrInfo &MII = TM.getInstrInfo(); - while (MBB.front()->getOpcode() == 0) { + while (MBB.front()->getOpcode() == MachineInstrInfo::PHI) { MachineInstr *MI = MBB.front(); - // Unlink the PHI node from the basic block... but don't delete the PHI + // Unlink the PHI node from the basic block... but don't delete the PHI yet MBB.erase(MBB.begin()); + DEBUG(std::cerr << "num invalid regs: " << RegsUsed.size() << "\n"); + DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n"); + assert(MI->getOperand(0).isVirtualRegister() && + "PHI node doesn't write virt reg?"); + // a preliminary pass that will invalidate any registers that // are used by the instruction (including implicit uses) invalidatePhysRegs(MI); - DEBUG(std::cerr << "num invalid regs: " << RegsUsed.size() << "\n"); - DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n"); - MachineOperand &targetReg = MI->getOperand(0); - - // If it's a virtual register, allocate a physical one otherwise, just use - // whatever register is there now note: it MUST be a register -- we're - // assigning to it! + // Allocate a physical reg to hold this temporary. // - unsigned virtualReg = (unsigned) targetReg.getAllocatedRegNum(); - unsigned physReg; - if (targetReg.isVirtualRegister()) { - physReg = getFreeReg(virtualReg); - } else { - physReg = virtualReg; - } + unsigned virtualReg = MI->getOperand(0).getAllocatedRegNum(); + unsigned physReg = getFreeReg(virtualReg); // Find the register class of the target register: should be the // same as the values we're trying to store there - const TargetRegisterClass* regClass = PhysRegClasses[physReg]; + const TargetRegisterClass* regClass = MF->getRegClass(virtualReg); assert(regClass && "Target register class not found!"); unsigned dataSize = regClass->getDataSize(); @@ -314,7 +297,7 @@ clearAllRegs(); } - // really delete the instruction + // really delete the PHI instruction now! delete MI; } } @@ -327,7 +310,7 @@ // loop over each instruction for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { // Made to combat the incorrect allocation of r2 = add r1, r1 - std::map VirtReg2PhysRegMap; + std::map Virt2PhysRegMap; MachineInstr *MI = *I; @@ -347,31 +330,26 @@ // make sure the same virtual register maps to the same physical // register in any given instruction - unsigned physReg; - if (VirtReg2PhysRegMap.find(virtualReg) != VirtReg2PhysRegMap.end()) { - physReg = VirtReg2PhysRegMap[virtualReg]; - } else { + unsigned physReg = Virt2PhysRegMap[virtualReg]; + if (physReg == 0) { if (op.opIsDef()) { if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) { // must be same register number as the first operand // This maps a = b + c into b += c, and saves b into a's spot assert(MI->getOperand(1).isRegister() && MI->getOperand(1).getAllocatedRegNum() && - MF->getRegClass(virtualReg) == - PhysRegClasses[MI->getOperand(1).getAllocatedRegNum()] && + MI->getOperand(1).opIsUse() && "Two address instruction invalid!"); physReg = MI->getOperand(1).getAllocatedRegNum(); } else { physReg = getFreeReg(virtualReg); } - MachineBasicBlock::iterator J = I; - J = saveVirtRegToStack(MBB, ++J, virtualReg, physReg); - I = --J; + I = --saveVirtRegToStack(MBB, ++I, virtualReg, physReg); } else { I = moveUseToReg(MBB, I, virtualReg, physReg); } - VirtReg2PhysRegMap[virtualReg] = physReg; + Virt2PhysRegMap[virtualReg] = physReg; } MI->SetMachineOperandReg(i, physReg); DEBUG(std::cerr << "virt: " << virtualReg << @@ -388,28 +366,26 @@ DEBUG(std::cerr << "Machine Function " << "\n"); MF = &Fn; + // Loop over all of the basic blocks, eliminating virtual register references for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; ++MBB) AllocateBasicBlock(*MBB); - // add prologue we should preserve callee-save registers... + // Add prologue to the function... RegInfo->emitPrologue(Fn, NumBytesAllocated); const MachineInstrInfo &MII = TM.getInstrInfo(); - // add epilogue to restore the callee-save registers - // loop over the basic block + // Add epilogue to restore the callee-save registers in each exiting block for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; ++MBB) { - // check if last instruction is a RET - if (MII.isReturn(MBB->back()->getOpcode())) { - // this block has a return instruction, add epilogue + // If last instruction is a return instruction, add an epilogue + if (MII.isReturn(MBB->back()->getOpcode())) RegInfo->emitEpilogue(*MBB, NumBytesAllocated); - } } cleanupAfterFunction(); - return false; // We never modify the LLVM itself. + return true; } Pass *createSimpleX86RegisterAllocator(TargetMachine &TM) { From lattner at cs.uiuc.edu Sun Dec 15 16:39:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 16:39:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp Message-ID: <200212152238.QAA02189@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.14 -> 1.15 --- Log message: Correct the setting of Def flags on registers that are modified! --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.14 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.15 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.14 Sun Dec 15 14:06:11 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Sun Dec 15 16:38:47 2002 @@ -56,8 +56,8 @@ const { static const unsigned Opcode[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32 }; - MachineInstr *MI = addRegOffset(BuildMI(Opcode[getIdx(dataSize)], 5) - .addReg(DestReg), SrcReg, ImmOffset); + MachineInstr *MI = addRegOffset(BuildMI(Opcode[getIdx(dataSize)], 4, DestReg), + SrcReg, ImmOffset); return ++MBB.insert(MBBI, MI); } @@ -68,8 +68,7 @@ unsigned dataSize) const { static const unsigned Opcode[] = { X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 }; - MachineInstr *MI = - BuildMI(Opcode[getIdx(dataSize)], 2).addReg(DestReg).addReg(SrcReg); + MachineInstr *MI = BuildMI(Opcode[getIdx(dataSize)],1,DestReg).addReg(SrcReg); return ++MBB.insert(MBBI, MI); } @@ -80,8 +79,7 @@ const { static const unsigned Opcode[] = { X86::MOVir8, X86::MOVir16, X86::MOVir32 }; - MachineInstr *MI = - BuildMI(Opcode[getIdx(dataSize)], 2).addReg(DestReg).addReg(Imm); + MachineInstr *MI = BuildMI(Opcode[getIdx(dataSize)], 1, DestReg).addReg(Imm); return ++MBB.insert(MBBI, MI); } @@ -113,15 +111,15 @@ MachineBasicBlock::iterator MBBI = MBB.begin(); // PUSH ebp - MachineInstr *MI = BuildMI (X86::PUSHr32, 1).addReg(X86::EBP); + MachineInstr *MI = BuildMI(X86::PUSHr32, 1).addReg(X86::EBP); MBBI = ++MBB.insert(MBBI, MI); // MOV ebp, esp - MI = BuildMI (X86::MOVrr32, 2).addReg(X86::EBP).addReg(X86::ESP); + MI = BuildMI(X86::MOVrr32, 1, X86::EBP).addReg(X86::ESP); MBBI = ++MBB.insert(MBBI, MI); - // adjust stack pointer - MI = BuildMI(X86::SUBri32, 2).addReg(X86::ESP).addZImm(numBytes); + // adjust stack pointer: ESP -= numbytes + MI = BuildMI(X86::SUBri32, 2, X86::ESP).addReg(X86::ESP).addZImm(numBytes); MBBI = ++MBB.insert(MBBI, MI); // PUSH all callee-save registers @@ -144,7 +142,7 @@ MRegisterInfo::NoRegister }; unsigned idx = 0; while (regs[idx]) { - MachineInstr *MI = BuildMI(X86::POPr32, 1).addReg(regs[idx++]); + MachineInstr *MI = BuildMI(X86::POPr32, 0, regs[idx++]); MBBI = ++(MBB.insert(MBBI, MI)); } From lattner at cs.uiuc.edu Sun Dec 15 16:41:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 16:41:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152240.QAA02210@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.26 -> 1.27 --- Log message: Simplify PHI node elimination significantly by doing it as a prepass to register allocation --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.26 llvm/lib/CodeGen/RegAllocSimple.cpp:1.27 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.26 Sun Dec 15 16:19:19 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 16:39:53 2002 @@ -212,6 +212,7 @@ /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in /// predecessor basic blocks. +/// void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) { const MachineInstrInfo &MII = TM.getInstrInfo(); @@ -220,26 +221,12 @@ // Unlink the PHI node from the basic block... but don't delete the PHI yet MBB.erase(MBB.begin()); - DEBUG(std::cerr << "num invalid regs: " << RegsUsed.size() << "\n"); DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n"); assert(MI->getOperand(0).isVirtualRegister() && "PHI node doesn't write virt reg?"); - // a preliminary pass that will invalidate any registers that - // are used by the instruction (including implicit uses) - invalidatePhysRegs(MI); - - // Allocate a physical reg to hold this temporary. - // unsigned virtualReg = MI->getOperand(0).getAllocatedRegNum(); - unsigned physReg = getFreeReg(virtualReg); - // Find the register class of the target register: should be the - // same as the values we're trying to store there - const TargetRegisterClass* regClass = MF->getRegClass(virtualReg); - assert(regClass && "Target register class not found!"); - unsigned dataSize = regClass->getDataSize(); - for (int i = MI->getNumOperands() - 1; i >= 2; i-=2) { MachineOperand &opVal = MI->getOperand(i-1); @@ -274,27 +261,20 @@ // are inserted right in front of it and not in front of a non-branch if (!MII.isBranch(opMI->getOpcode())) ++opI; - + + unsigned dataSize = MF->getRegClass(virtualReg)->getDataSize(); + // Retrieve the constant value from this op, move it to target // register of the phi if (opVal.isImmediate()) { - opI = RegInfo->moveImm2Reg(opBlock, opI, physReg, + opI = RegInfo->moveImm2Reg(opBlock, opI, virtualReg, (unsigned) opVal.getImmedValue(), dataSize); } else { - // Allocate a physical register and add a move in the BB - unsigned opVirtualReg = opVal.getAllocatedRegNum(); - unsigned opPhysReg; - opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg); - + opI = RegInfo->moveReg2Reg(opBlock, opI, virtualReg, + opVal.getAllocatedRegNum(), dataSize); } - - // Save that register value to the stack of the TARGET REG - saveVirtRegToStack(opBlock, opI, virtualReg, physReg); } - - // make regs available to other instructions - clearAllRegs(); } // really delete the PHI instruction now! @@ -304,9 +284,6 @@ void RegAllocSimple::AllocateBasicBlock(MachineBasicBlock &MBB) { - // Handle PHI instructions specially: add moves to each pred block - EliminatePHINodes(MBB); - // loop over each instruction for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { // Made to combat the incorrect allocation of r2 = add r1, r1 @@ -365,6 +342,12 @@ bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) { DEBUG(std::cerr << "Machine Function " << "\n"); MF = &Fn; + + // First pass: eliminate PHI instructions by inserting copies into predecessor + // blocks. + for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); + MBB != MBBe; ++MBB) + EliminatePHINodes(*MBB); // Loop over all of the basic blocks, eliminating virtual register references for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); From lattner at cs.uiuc.edu Sun Dec 15 17:02:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 17:02:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212152301.RAA02484@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.27 -> 1.28 --- Log message: Some simpliciations to the spill/reload interface --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.27 llvm/lib/CodeGen/RegAllocSimple.cpp:1.28 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.27 Sun Dec 15 16:39:53 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Sun Dec 15 17:01:26 2002 @@ -126,14 +126,12 @@ } /// Moves value from memory into that register - MachineBasicBlock::iterator - moveUseToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned VirtReg, unsigned &PhysReg); + unsigned reloadVirtReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &I, unsigned VirtReg); /// Saves reg value on the stack (maps virtual register to stack value) - MachineBasicBlock::iterator - saveVirtRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned VirtReg, unsigned PhysReg); + void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, + unsigned VirtReg, unsigned PhysReg); }; } @@ -178,35 +176,31 @@ return getFreeReg(virtualReg); } -MachineBasicBlock::iterator -RegAllocSimple::moveUseToReg (MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned VirtReg, unsigned &PhysReg) -{ +unsigned RegAllocSimple::reloadVirtReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &I, + unsigned VirtReg) { const TargetRegisterClass* regClass = MF->getRegClass(VirtReg); unsigned stackOffset = getStackSpaceFor(VirtReg, regClass); - PhysReg = getFreeReg(VirtReg); + unsigned PhysReg = getFreeReg(VirtReg); // Add move instruction(s) ++NumReloaded; - return RegInfo->loadRegOffset2Reg(MBB, I, PhysReg, - RegInfo->getFramePointer(), - -stackOffset, regClass->getDataSize()); + I = RegInfo->loadRegOffset2Reg(MBB, I, PhysReg, RegInfo->getFramePointer(), + -stackOffset, regClass->getDataSize()); + return PhysReg; } -MachineBasicBlock::iterator -RegAllocSimple::saveVirtRegToStack (MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned VirtReg, unsigned PhysReg) +void RegAllocSimple::spillVirtReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &I, + unsigned VirtReg, unsigned PhysReg) { const TargetRegisterClass* regClass = MF->getRegClass(VirtReg); unsigned stackOffset = getStackSpaceFor(VirtReg, regClass); // Add move instruction(s) ++NumSpilled; - return RegInfo->storeReg2RegOffset(MBB, I, PhysReg, - RegInfo->getFramePointer(), - -stackOffset, regClass->getDataSize()); + I = RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(), + -stackOffset, regClass->getDataSize()); } @@ -322,11 +316,13 @@ } else { physReg = getFreeReg(virtualReg); } - I = --saveVirtRegToStack(MBB, ++I, virtualReg, physReg); + ++I; + spillVirtReg(MBB, I, virtualReg, physReg); + --I; } else { - I = moveUseToReg(MBB, I, virtualReg, physReg); + physReg = reloadVirtReg(MBB, I, virtualReg); + Virt2PhysRegMap[virtualReg] = physReg; } - Virt2PhysRegMap[virtualReg] = physReg; } MI->SetMachineOperandReg(i, physReg); DEBUG(std::cerr << "virt: " << virtualReg << From vadve at cs.uiuc.edu Sun Dec 15 19:32:00 2002 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Sun Dec 15 19:32:00 2002 Subject: [llvm-commits] CVS: llvm/Makefile.common Message-ID: <200212160131.TAA15305@tank.cs.uiuc.edu> Changes in directory llvm: Makefile.common updated: 1.69 -> 1.70 --- Log message: Use -Wl,-x instead of -s: it is more portable, and in particular, is needed on BSD (MacOS). Also, use -Ldir instead of -L dir on the link line. Same reason... --- Diffs of the changes: Index: llvm/Makefile.common diff -u llvm/Makefile.common:1.69 llvm/Makefile.common:1.70 --- llvm/Makefile.common:1.69 Wed Dec 4 11:08:15 2002 +++ llvm/Makefile.common Sun Dec 15 19:31:18 2002 @@ -144,7 +144,7 @@ STRIP = WARN_MSG = else -STRIP = -s +STRIP = -Wl,-x WARN_MSG = "(without symbols) " endif @@ -174,9 +174,9 @@ else Link := $(CXX) endif -LinkG := $(Link) -g -L $(LIBDEBUG) $(STRIP) -LinkO := $(Link) -O3 -L $(LIBRELEASE) -LinkP := $(Link) -O3 -L $(LIBPROFILE) $(PROFILE) +LinkG := $(Link) -g -L$(LIBDEBUG) $(STRIP) +LinkO := $(Link) -O3 -L$(LIBRELEASE) +LinkP := $(Link) -O3 -L$(LIBPROFILE) $(PROFILE) # Create one .o file from a bunch of .o files... Relink = ld -r From lattner at cs.uiuc.edu Sun Dec 15 22:24:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 15 22:24:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212160423.WAA16717@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.70 -> 1.71 --- Log message: brg Fix some bugs in use of MBB vs. BB and iterators that are invalidated before we use them. Reference targetClass by enum name, not by number. --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.70 llvm/lib/Target/X86/InstSelectSimple.cpp:1.71 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.70 Sun Dec 15 15:13:40 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Sun Dec 15 22:23:29 2002 @@ -292,7 +292,7 @@ MachineBasicBlock::iterator &IP) { if (ConstantExpr *CE = dyn_cast(C)) { if (CE->getOpcode() == Instruction::GetElementPtr) { - emitGEPOperation(BB, IP, CE->getOperand(0), + emitGEPOperation(MBB, IP, CE->getOperand(0), CE->op_begin()+1, CE->op_end(), R); return; } @@ -322,7 +322,7 @@ // Copy zero (null pointer) to the register. BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(0); } else if (ConstantPointerRef *CPR = dyn_cast(C)) { - unsigned SrcReg = getReg(CPR->getValue(), BB, IP); + unsigned SrcReg = getReg(CPR->getValue(), MBB, IP); BMI(MBB, IP, X86::MOVrr32, 1, R).addReg(SrcReg); } else { std::cerr << "Offending constant: " << C << "\n"; @@ -888,12 +888,12 @@ // 2) Implement casts between values of the same type class (as determined // by getClass) by using a register-to-register move. - unsigned srcClass = getClassB(sourceType); + unsigned srcClass = getClassB (sourceType); unsigned targClass = getClass (targetType); static const unsigned regRegMove[] = { X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 }; - if ((srcClass < 3) && (targClass < 3) && (srcClass == targClass)) + if ((srcClass < cLong) && (targClass < cLong) && (srcClass == targClass)) { BuildMI (BB, regRegMove[srcClass], 1, destReg).addReg (operandReg); return; @@ -901,7 +901,7 @@ // 3) Handle cast of SMALLER int to LARGER int using a move with sign // extension or zero extension, depending on whether the source type // was signed. - if ((srcClass < 3) && (targClass < 3) && (srcClass < targClass)) + if ((srcClass < cLong) && (targClass < cLong) && (srcClass < targClass)) { static const unsigned ops[] = { X86::MOVSXr16r8, X86::MOVSXr32r8, X86::MOVSXr32r16, @@ -914,7 +914,7 @@ } // 4) Handle cast of LARGER int to SMALLER int using a move to EAX // followed by a move out of AX or AL. - if ((srcClass < 3) && (targClass < 3) && (srcClass > targClass)) + if ((srcClass < cLong) && (targClass < cLong) && (srcClass > targClass)) { static const unsigned AReg[] = { X86::AL, X86::AX, X86::EAX }; BuildMI (BB, regRegMove[srcClass], 1, @@ -943,9 +943,10 @@ void ISel::visitGetElementPtrInst (GetElementPtrInst &I) { + unsigned outputReg = getReg (I); MachineBasicBlock::iterator MI = BB->end(); emitGEPOperation(BB, MI, I.getOperand(0), - I.op_begin()+1, I.op_end(), getReg(I)); + I.op_begin()+1, I.op_end(), outputReg); } void ISel::emitGEPOperation(MachineBasicBlock *MBB, @@ -954,7 +955,7 @@ User::op_iterator IdxEnd, unsigned TargetReg) { const TargetData &TD = TM.getTargetData(); const Type *Ty = Src->getType(); - unsigned basePtrReg = getReg(Src, BB, IP); + unsigned basePtrReg = getReg(Src, MBB, IP); // GEPs have zero or more indices; we must perform a struct access // or array access for each one. @@ -999,14 +1000,14 @@ unsigned elementSizeReg = makeAnotherReg(typeOfSequentialTypeIndex); copyConstantToRegister(ConstantSInt::get(typeOfSequentialTypeIndex, elementSize), elementSizeReg, - BB, IP); + MBB, IP); - unsigned idxReg = getReg(idx, BB, IP); + unsigned idxReg = getReg(idx, MBB, IP); // Emit a MUL to multiply the register holding the index by // elementSize, putting the result in memberOffsetReg. unsigned memberOffsetReg = makeAnotherReg(Type::UIntTy); doMultiply (memberOffsetReg, typeOfSequentialTypeIndex, - elementSizeReg, idxReg, BB, IP); + elementSizeReg, idxReg, MBB, IP); // Emit an ADD to add memberOffsetReg to the basePtr. BMI(MBB, IP, X86::ADDrr32, 2, nextBasePtrReg).addReg (basePtrReg).addReg (memberOffsetReg);
Dec 14th, 2002 -Added Chris Lattner's Master's Thesis to the + publications list.
Oct 28th, 2002 -