From lattner at cs.uiuc.edu Tue May 6 13:46:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 6 13:46:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Bytecode/Primitives.h Message-ID: <200305061845.NAA30740@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Bytecode: Primitives.h updated: 1.7 -> 1.8 --- Log message: Fix memory corruption problem --- Diffs of the changes: Index: llvm/include/llvm/Bytecode/Primitives.h diff -u llvm/include/llvm/Bytecode/Primitives.h:1.7 llvm/include/llvm/Bytecode/Primitives.h:1.8 --- llvm/include/llvm/Bytecode/Primitives.h:1.7 Tue Sep 17 18:48:02 2002 +++ llvm/include/llvm/Bytecode/Primitives.h Tue May 6 13:45:02 2003 @@ -163,7 +163,8 @@ if (pos == -1) Out.insert(Out.end(), (unsigned char*)&i, (unsigned char*)&i+4); else - *(unsigned*)&Out[pos] = i; + // This cannot use block copy because deques are not guaranteed contiguous! + std::copy((unsigned char*)&i, 4+(unsigned char*)&i, Out.begin()+pos); #else if (pos == -1) { // Be endian clean, little endian is our friend Out.push_back((unsigned char)i); From lattner at cs.uiuc.edu Tue May 6 14:04:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 6 14:04:03 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Makefile.multisrc Message-ID: <200305061903.OAA32509@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource: Makefile.multisrc updated: 1.26 -> 1.27 --- Log message: For now, don't optimize multisource tests by the native compiler --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/Makefile.multisrc diff -u llvm/test/Programs/MultiSource/Makefile.multisrc:1.26 llvm/test/Programs/MultiSource/Makefile.multisrc:1.27 --- llvm/test/Programs/MultiSource/Makefile.multisrc:1.26 Thu Apr 24 22:57:08 2003 +++ llvm/test/Programs/MultiSource/Makefile.multisrc Tue May 6 14:03:22 2003 @@ -32,7 +32,7 @@ .PRECIOUS: $(LObjects) $(NObjects) Output/%.linked.rll Output/%.o: %.c Output/.dir - $(CC) $(CPPFLAGS) -O $(CFLAGS) -c $< -o $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ bugpoint-gccas: Output/$(PROG).bugpoint-gccas bugpoint-gccld: Output/$(PROG).bugpoint-gccld From lattner at cs.uiuc.edu Tue May 6 14:05:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 6 14:05:02 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/Makefile Message-ID: <200305061904.OAA32526@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms: Makefile updated: 1.21 -> 1.22 --- Log message: Make sure to compiel the LowerSwitch tests --- Diffs of the changes: Index: llvm/test/Regression/Transforms/Makefile diff -u llvm/test/Regression/Transforms/Makefile:1.21 llvm/test/Regression/Transforms/Makefile:1.22 --- llvm/test/Regression/Transforms/Makefile:1.21 Wed Apr 16 15:23:42 2003 +++ llvm/test/Regression/Transforms/Makefile Tue May 6 14:04:02 2003 @@ -14,6 +14,7 @@ InstCombine \ LevelRaise \ LICM \ + LowerSwitch \ Mem2Reg \ PiNodeInserter \ PRE \ From lattner at cs.uiuc.edu Tue May 6 14:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 6 14:42:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/2003-05-06-LivenessClobber.llx Message-ID: <200305061941.OAA01173@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: 2003-05-06-LivenessClobber.llx added (r1.1) --- Log message: New testcase distilled from the fhourstones benchmark --- Diffs of the changes: Index: llvm/test/Regression/Jello/2003-05-06-LivenessClobber.llx diff -c /dev/null llvm/test/Regression/Jello/2003-05-06-LivenessClobber.llx:1.1 *** /dev/null Tue May 6 14:41:35 2003 --- llvm/test/Regression/Jello/2003-05-06-LivenessClobber.llx Tue May 6 14:41:25 2003 *************** *** 0 **** --- 1,26 ---- + ; This testcase shoudl return with an exit code of 1. + ; + ; RUN: if as < %s | lli -force-interpreter=false + ; RUN: then exit 1 + ; RUN: else exit 0 + ; RUN: fi + + target endian = little + target pointersize = 32 + + %test = global long 0 + implementation + + + internal long %test() { + %tmp.0 = load long* %test ; [#uses=1] + %tmp.1 = add long %tmp.0, 1 ; [#uses=1] + ret long %tmp.1 + } + + int %main() { + %L = call long %test() + %I = cast long %L to int + ret int %I + } + From lattner at cs.uiuc.edu Tue May 6 15:48:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 6 15:48:01 2003 Subject: [llvm-commits] CVS: llvm/www/docs/OpenProjects.html Message-ID: <200305062047.PAA17935@tank.cs.uiuc.edu> Changes in directory llvm/www/docs: OpenProjects.html updated: 1.5 -> 1.6 --- Log message: Add a new open project --- Diffs of the changes: Index: llvm/www/docs/OpenProjects.html diff -u llvm/www/docs/OpenProjects.html:1.5 llvm/www/docs/OpenProjects.html:1.6 --- llvm/www/docs/OpenProjects.html:1.5 Sun Apr 27 22:42:31 2003 +++ llvm/www/docs/OpenProjects.html Tue May 6 15:47:11 2003 @@ -147,6 +147,11 @@ From brukman at cs.uiuc.edu Wed May 7 16:53:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 7 16:53:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9.td Message-ID: <200305072152.QAA23774@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9.td added (r1.1) --- Log message: Added the initial version of the TableGen description for the Sparc backend. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9.td diff -c /dev/null llvm/lib/Target/Sparc/SparcV9.td:1.1 *** /dev/null Wed May 7 16:52:50 2003 --- llvm/lib/Target/Sparc/SparcV9.td Wed May 7 16:52:39 2003 *************** *** 0 **** --- 1,359 ---- + //===- Sparc.td - Target Description for Sparc V9 Target --------*- C++ -*-===// + // + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Target-Independent interface + //===----------------------------------------------------------------------===// + + class Register { + string Namespace = ""; + int Size; + } + + class Instruction { + string Name; // The opcode string for this instruction + string Namespace = ""; + + list Uses = []; // Default to using no non-operand registers + list Defs = []; // Default to modifying no non-operand registers + + // These bits capture information about the high-level semantics of the + // instruction. + bit isReturn = 0; // Is this instruction a return instruction? + bit isBranch = 0; // Is this instruction a branch instruction? + bit isCall = 0; // Is this instruction a call instruction? + } + + + //===----------------------------------------------------------------------===// + // Declarations that describe the Sparc register file + //===----------------------------------------------------------------------===// + + class V9Reg : Register { set Namespace = "SparcV9"; } + + // Ri - One of the 32 64 bit integer registers + class Ri num> : V9Reg { set Size = 64; field bits<5> Num = num; } + + def G0 : Ri<0>; def G1 : Ri<1>; def G2 : Ri<2>; def G3 : Ri<3>; + // ... + + + //===----------------------------------------------------------------------===// + // This is temporary testing stuff..... + //===----------------------------------------------------------------------===// + + class InstV9 : Instruction { // Sparc instruction baseline + field bits<32> Inst; + + set Namespace = "SparcV9"; + + bits<2> op; + set Inst{31-30} = op; // Top two bits are the 'op' field + + // Bit attributes specific to Sparc instructions + bit isPasi = 0; // Does this instruction affect an alternate addr space? + bit isDeprecated = 0; // Is this instruction deprecated? + bit isPrivileged = 0; // Is this a privileged instruction? + } + + + //===----------------------------------------------------------------------===// + // Format #2 classes + // + class F2 : InstV9 { // Format 2 instructions + bits<3> op2; + set op = 0; // Op = 0 + set Inst{24-22} = op2; + } + + class F2_br : F2 { // Format 2 Branch instruction + bit annul; // All branches have an annul bit + set Inst{29} = annul; + set isBranch = 1; // All instances are branch instructions + } + + class F2_2 cond, string name> : F2_br { // Format 2.2 instructions + bits<22> disp; + + set Name = name; + set Inst{28-25} = cond; + set Inst{21-0} = disp; + } + + class F2_3 cond, string name> : F2_br { // Format 2.3 instructions + bits<2> cc; + bits<19> disp; + bit predict; + + set Name = name; + set Inst{28-25} = cond; + set Inst{21-20} = cc; + set Inst{19} = predict; + set Inst{18-0} = disp; + } + + class F2_4 rcond, string name> : F2_br { // Format 2.4 instructions + // Variables exposed by the instruction... + bit predict; + bits<5> rs1; + bits<16> disp; + + set Name = name; + set Inst{28} = 0; + set Inst{27-25} = rcond; + // Inst{24-22} = op2 field + set Inst{21-20} = disp{15-14}; + set Inst{19} = predict; + set Inst{18-14} = rs1; + set Inst{13-0 } = disp{13-0}; + } + + + //===----------------------------------------------------------------------===// + // Format #3 classes + // + + // F3 - Common superclass of all F3 instructions. All instructions have an op3 + // field. + class F3 : InstV9 { + bits<6> op3; + set op{1} = 1; // Op = 2 or 3 + set Inst{24-19} = op3; + } + + // F3_rs1 - Common superclass of instructions that use rs1 + class F3_rs1 : F3 { + bits<5> rs1; + set Inst{18-14} = rs1; + } + + // F3_rs1rd - Common superclass of instructions that use rs1 & rd... + class F3_rs1rd : F3_rs1 { + bits<5> rd; + set Inst{29-25} = rd; + } + + // F3_rs1rdrs2 - Common superclass of instructions with rs1, rd, & rs2 fields + class F3_rs1rdrs2 : F3_rs1 { + bits<5> rs2; + set Inst{4-0} = rs2; + } + + // Specific F3 classes... + // + + class F3_1 opVal, bits<6> op3val, string name> : F3_rs1rdrs2 { + set op = opVal; + set op3 = op3val; + set Name = name; + set Inst{13} = 0; // i field = 0 + //set Inst{12-5} = dontcare; + } + + class F3_2 opVal, bits<6> op3val, string name> : F3_rs1rd { + bits<13> simm; + + set op = opVal; + set op3 = op3val; + set Name = name; + set Inst{13} = 1; // i field = 1 + set Inst{12-0} = simm; + } + + class F3_3 opVal, bits<6> op3val, string name> : F3_rs1 { + bits<5> rs2; + set op = opVal; + set op3 = op3val; + set Name = name; + //set Inst{29-25} = dontcare; + set Inst{13} = 0; + //set Inst{12-5} = dontcare; + set Inst{4-0} = rs2; + } + + class F3_4 opVal, bits<6> op3val, string name> : F3_rs1 { + bits<13> simm; + set op = opVal; + set op3 = op3val; + set Name = name; + //set Inst{29-25} = dontcare; + set Inst{13} = 1; + set Inst{12-0} = simm; + } + + + + class F3_16 opVal, bits<6> op3val, + bits<9> opfval, string name> : F3_rs1rdrs2 { + set op = opVal; + set op3 = op3val; + set Name = name; + set Inst{13-5} = opfval; + } + + class F3_18 fcn, string name> : F3 { + set op = 2; + set op3 = 0b111110; + set Name = name; + set Inst{29-25} = fcn; + //set Inst{18-0 } = dontcare; + } + + //===----------------------------------------------------------------------===// + // Instruction list... + // + + // Section A.2: p161 + def ADDr : F3_1<2, 0b000000, "add">; // add r, r, r + def ADDi : F3_2<2, 0b000000, "add">; // add r, r, i + def ADDCCr : F3_1<2, 0b010000, "addcc">; // addcc r, r, r + def ADDCCi : F3_2<2, 0b010000, "addcc">; // addcc r, r, i + def ADDCr : F3_1<2, 0b001000, "addC">; // addC r, r, r + def ADDCi : F3_2<2, 0b001000, "addC">; // addC r, r, i + def ADDCCCr : F3_1<2, 0b011000, "addCcc">; // addCcc r, r, r + def ADDCCCi : F3_2<2, 0b011000, "addCcc">; // addCcc r, r, i + + // Section A.3: p162 + set op2 = 0b011 in { + def BRZ : F2_4<0b001, "brz">; // Branch on rs1 == 0 + def BRLEZ : F2_4<0b010, "brlez">; // Branch on rs1 <= 0 + def BRLZ : F2_4<0b011, "brlz">; // Branch on rs1 < 0 + def BRNZ : F2_4<0b101, "brnz">; // Branch on rs1 != 0 + def BRGZ : F2_4<0b110, "brgz">; // Branch on rs1 > 0 + def BRGEZ : F2_4<0b111, "brgez">; // Branch on rs1 >= 0 + } + + // Section A.4: p164 + set isDeprecated = 1 in { + set op2 = 0b110 in { + def FBA : F2_2<0b1000, "fba">; // Branch always + def FBN : F2_2<0b0000, "fbn">; // Branch never + def FBU : F2_2<0b0111, "fbu">; // Branch on unordered + def FBG : F2_2<0b0110, "fbg">; // Branch > + def FBUG : F2_2<0b0101, "fbug">; // Branch on unordered or > + def FBL : F2_2<0b0100, "fbl">; // Branch < + def FBUL : F2_2<0b0011, "fbul">; // Branch on unordered or < + def FBLG : F2_2<0b0010, "fblg">; // Branch < or > + def FBNE : F2_2<0b0001, "fbne">; // Branch != + def FBE : F2_2<0b1001, "fbe">; // Branch == + def FBUE : F2_2<0b1010, "fbue">; // Branch on unordered or == + def FBGE : F2_2<0b1011, "fbge">; // Branch > or == + def FBUGE : F2_2<0b1100, "fbuge">; // Branch unord or > or == + def FBLE : F2_2<0b1101, "fble">; // Branch < or == + def FBULE : F2_2<0b1110, "fbule">; // Branch unord or < or == + def FBO : F2_2<0b1111, "fbo">; // Branch on ordered + } + } + + // Section A.5: p167 + set op2 = 0b101 in { + def FBPA : F2_3<0b1000, "fbpa">; // Branch always + def FBPN : F2_3<0b0000, "fbpn">; // Branch never + def FBPU : F2_3<0b0111, "fbpu">; // Branch on unordered + def FBPG : F2_3<0b0110, "fbpg">; // Branch > + def FBPUG : F2_3<0b0101, "fbpug">; // Branch on unordered or > + def FBPL : F2_3<0b0100, "fbpl">; // Branch < + def FBPUL : F2_3<0b0011, "fbpul">; // Branch on unordered or < + def FBPLG : F2_3<0b0010, "fbplg">; // Branch < or > + def FBPNE : F2_3<0b0001, "fbpne">; // Branch != + def FBPE : F2_3<0b1001, "fbpe">; // Branch == + def FBPUE : F2_3<0b1010, "fbpue">; // Branch on unordered or == + def FBPGE : F2_3<0b1011, "fbpge">; // Branch > or == + def FBPUGE : F2_3<0b1100, "fbpuge">; // Branch unord or > or == + def FBPLE : F2_3<0b1101, "fbple">; // Branch < or == + def FBPULE : F2_3<0b1110, "fbpule">; // Branch unord or < or == + def FBPO : F2_3<0b1111, "fbpo">; // Branch on ordered + } + + // Section A.6: p170: Bicc + set isDeprecated = 1 in { + set op2 = 0b010 in { + def BA : F2_2<0b1000, "ba">; // Branch always + def BN : F2_2<0b0000, "bn">; // Branch never + def BNE : F2_2<0b1001, "bne">; // Branch != + def BE : F2_2<0b0001, "be">; // Branch == + def BG : F2_2<0b1010, "bg">; // Branch > + def BLE : F2_2<0b0010, "ble">; // Branch <= + def BGE : F2_2<0b1011, "bge">; // Branch >= + def BL : F2_2<0b0011, "bl">; // Branch < + def BGU : F2_2<0b1100, "bgu">; // Branch unsigned > + def BLEU : F2_2<0b0100, "bleu">; // Branch unsigned <= + def BCC : F2_2<0b1101, "bcc">; // Branch unsigned >= + def BCS : F2_2<0b0101, "bcs">; // Branch unsigned <= + def BPOS : F2_2<0b1110, "bpos">; // Branch on positive + def BNEG : F2_2<0b0110, "bneg">; // Branch on negative + def BVC : F2_2<0b1111, "bvc">; // Branch on overflow clear + def BVS : F2_2<0b0111, "bvs">; // Branch on overflow set + } + } + + // Section A.7: p172 + set op2 = 0b001 in { + def BPA : F2_3<0b1000, "bpa">; // Branch always + def BPN : F2_3<0b0000, "bpn">; // Branch never + def BPNE : F2_3<0b1001, "bpne">; // Branch != + def BPE : F2_3<0b0001, "bpe">; // Branch == + def BPG : F2_3<0b1010, "bpg">; // Branch > + def BPLE : F2_3<0b0010, "bple">; // Branch <= + def BPGE : F2_3<0b1011, "bpge">; // Branch >= + def BPL : F2_3<0b0011, "bpl">; // Branch < + def BPGU : F2_3<0b1100, "bpgu">; // Branch unsigned > + + def BPLEU : F2_3<0b0100, "bpleu">; // Branch unsigned <= + def BPCC : F2_3<0b1101, "bpcc">; // Branch unsigned >= + def BPCS : F2_3<0b0101, "bpcs">; // Branch unsigned <= + def BPPOS : F2_3<0b1110, "bppos">; // Branch on positive + def BPNEG : F2_3<0b0110, "bpneg">; // Branch on negative + def BPVC : F2_3<0b1111, "bpvc">; // Branch on overflow clear + def BPVS : F2_3<0b0111, "bpvs">; // Branch on overflow set + } + + // Section A.8: p175 - CALL - the only Format #1 instruction + def CALL : InstV9 { + bits<30> disp; + set op = 1; + set Inst{29-0} = disp; + set Name = "call"; + set isCall = 1; + } + + // Section A.9: Compare and Swap - p176 + // CASA/CASXA: are for alternate address spaces! Ignore them + + + // Section A.10: Divide (64-bit / 32-bit) - p178 + set isDeprecated = 1 in { + def UDIVr : F3_1<2, 0b001110, "udiv">; // udiv r, r, r + def UDIVi : F3_2<2, 0b001110, "udiv">; // udiv r, r, i + def SDIVr : F3_1<2, 0b001111, "sdiv">; // sdiv r, r, r + def SDIVi : F3_2<2, 0b001111, "sdiv">; // sdiv r, r, i + def UDIVCCr : F3_1<2, 0b011110, "udivcc">; // udivcc r, r, r + def UDIVCCi : F3_2<2, 0b011110, "udivcc">; // udivcc r, r, i + def SDIVCCr : F3_1<2, 0b011111, "sdivcc">; // sdivcc r, r, r + def SDIVCCi : F3_2<2, 0b011111, "sdivcc">; // sdivcc r, r, i + } + + // Section A.11: DONE and RETRY - p181 + set isPrivileged = 1 in { + def DONE : F3_18<0, "done">; // done + def RETRY : F3_18<1, "retry">; // retry + } + + // Section A.12: Floating-Point Add and Subtract - p182 + def FADDS : F3_16<2, 0b110100, 0x41, "fadds">; // fadds f, f, f + def FADDD : F3_16<2, 0b110100, 0x42, "faddd">; // faddd f, f, f + def FADDQ : F3_16<2, 0b110100, 0x43, "faddq">; // faddq f, f, f + def FSUBS : F3_16<2, 0b110100, 0x45, "fsubs">; // fsubs f, f, f + def FSUBD : F3_16<2, 0b110100, 0x46, "fsubd">; // fsubd f, f, f + def FSUBQ : F3_16<2, 0b110100, 0x47, "fsubq">; // fsubq f, f, f + + // + // ... + // + + // Section A.45: RETURN - p240 + set isReturn = 1 in { + def RETURNr : F3_3<2, 0b111001, "return">; // return + def RETURNi : F3_4<2, 0b111001, "return">; // return + } From lattner at cs.uiuc.edu Wed May 7 21:09:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:09:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/AsmWriter.cpp Message-ID: <200305080208.VAA27627@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: AsmWriter.cpp updated: 1.84 -> 1.85 --- Log message: Remove using declarations --- Diffs of the changes: Index: llvm/lib/VMCore/AsmWriter.cpp diff -u llvm/lib/VMCore/AsmWriter.cpp:1.84 llvm/lib/VMCore/AsmWriter.cpp:1.85 --- llvm/lib/VMCore/AsmWriter.cpp:1.84 Tue Apr 22 14:07:19 2003 +++ llvm/lib/VMCore/AsmWriter.cpp Wed May 7 21:08:14 2003 @@ -25,18 +25,15 @@ #include "Support/StringExtras.h" #include "Support/STLExtras.h" #include -using std::string; -using std::map; -using std::vector; -using std::ostream; static RegisterPass X("printm", "Print module to stderr",PassInfo::Analysis|PassInfo::Optimization); static RegisterPass Y("print","Print function to stderr",PassInfo::Analysis|PassInfo::Optimization); -static void WriteAsOperandInternal(ostream &Out, const Value *V, bool PrintName, - map &TypeTable, +static void WriteAsOperandInternal(std::ostream &Out, const Value *V, + bool PrintName, + std::map &TypeTable, SlotCalculator *Table); static const Module *getModuleFromVal(const Value *V) { @@ -73,7 +70,7 @@ // names into the TypeNames map. // static void fillTypeNameTable(const Module *M, - map &TypeNames) { + std::map &TypeNames) { if (!M) return; const SymbolTable &ST = M->getSymbolTable(); SymbolTable::const_iterator PI = ST.find(Type::TypeTy); @@ -93,12 +90,13 @@ -static string calcTypeName(const Type *Ty, vector &TypeStack, - map &TypeNames) { +static std::string calcTypeName(const Type *Ty, + std::vector &TypeStack, + std::map &TypeNames){ if (Ty->isPrimitiveType()) return Ty->getDescription(); // Base case // Check to see if the type is named. - map::iterator I = TypeNames.find(Ty); + std::map::iterator I = TypeNames.find(Ty); if (I != TypeNames.end()) return I->second; // Check to see if the Type is already on the stack... @@ -114,7 +112,7 @@ TypeStack.push_back(Ty); // Recursive case: Add us to the stack.. - string Result; + std::string Result; switch (Ty->getPrimitiveID()) { case Type::FunctionTyID: { const FunctionType *FTy = cast(Ty); @@ -168,23 +166,23 @@ // printTypeInt - The internal guts of printing out a type that has a // potentially named portion. // -static ostream &printTypeInt(ostream &Out, const Type *Ty, - map &TypeNames) { +static std::ostream &printTypeInt(std::ostream &Out, const Type *Ty, + std::map &TypeNames) { // Primitive types always print out their description, regardless of whether // they have been named or not. // if (Ty->isPrimitiveType()) return Out << Ty->getDescription(); // Check to see if the type is named. - map::iterator I = TypeNames.find(Ty); + std::map::iterator I = TypeNames.find(Ty); if (I != TypeNames.end()) return Out << I->second; // Otherwise we have a type that has not been named but is a derived type. // Carefully recurse the type hierarchy to print out any contained symbolic // names. // - vector TypeStack; - string TypeName = calcTypeName(Ty, TypeStack, TypeNames); + std::vector TypeStack; + std::string TypeName = calcTypeName(Ty, TypeStack, TypeNames); TypeNames.insert(std::make_pair(Ty, TypeName));//Cache type name for later use return Out << TypeName; } @@ -194,13 +192,14 @@ // type, iff there is an entry in the modules symbol table for the specified // type or one of it's component types. This is slower than a simple x << Type; // -ostream &WriteTypeSymbolic(ostream &Out, const Type *Ty, const Module *M) { +std::ostream &WriteTypeSymbolic(std::ostream &Out, const Type *Ty, + const Module *M) { Out << " "; // If they want us to print out a type, attempt to make it symbolic if there // is a symbol table in the module... if (M) { - map TypeNames; + std::map TypeNames; fillTypeNameTable(M, TypeNames); return printTypeInt(Out, Ty, TypeNames); @@ -209,8 +208,9 @@ } } -static void WriteConstantInt(ostream &Out, const Constant *CV, bool PrintName, - map &TypeTable, +static void WriteConstantInt(std::ostream &Out, const Constant *CV, + bool PrintName, + std::map &TypeTable, SlotCalculator *Table) { if (const ConstantBool *CB = dyn_cast(CV)) { Out << (CB == ConstantBool::True ? "true" : "false"); @@ -359,8 +359,9 @@ // ostream. This can be useful when you just want to print int %reg126, not the // whole instruction that generated it. // -static void WriteAsOperandInternal(ostream &Out, const Value *V, bool PrintName, - map &TypeTable, +static void WriteAsOperandInternal(std::ostream &Out, const Value *V, + bool PrintName, + std::map &TypeTable, SlotCalculator *Table) { Out << " "; if (PrintName && V->hasName()) { @@ -397,9 +398,9 @@ // ostream. This can be useful when you just want to print int %reg126, not the // whole instruction that generated it. // -ostream &WriteAsOperand(ostream &Out, const Value *V, bool PrintType, - bool PrintName, const Module *Context) { - map TypeNames; +std::ostream &WriteAsOperand(std::ostream &Out, const Value *V, bool PrintType, + bool PrintName, const Module *Context) { + std::map TypeNames; if (Context == 0) Context = getModuleFromVal(V); if (Context) @@ -415,12 +416,12 @@ class AssemblyWriter { - ostream &Out; + std::ostream &Out; SlotCalculator &Table; const Module *TheModule; - map TypeNames; + std::map TypeNames; public: - inline AssemblyWriter(ostream &o, SlotCalculator &Tab, const Module *M) + inline AssemblyWriter(std::ostream &o, SlotCalculator &Tab, const Module *M) : Out(o), Table(Tab), TheModule(M) { // If the module has a symbol table, take all global types and stuff their @@ -452,14 +453,14 @@ // printType - Go to extreme measures to attempt to print out a short, // symbolic version of a type name. // - ostream &printType(const Type *Ty) { + std::ostream &printType(const Type *Ty) { return printTypeInt(Out, Ty, TypeNames); } // printTypeAtLeastOneLevel - Print out one level of the possibly complex type // without considering any symbolic types that we may have equal to it. // - ostream &printTypeAtLeastOneLevel(const Type *Ty); + std::ostream &printTypeAtLeastOneLevel(const Type *Ty); // printInfoComment - Print a little comment after the instruction indicating // which slot it occupies. @@ -470,7 +471,7 @@ // printTypeAtLeastOneLevel - Print out one level of the possibly complex type // without considering any symbolic types that we may have equal to it. // -ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) { +std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) { if (const FunctionType *FTy = dyn_cast(Ty)) { printType(FTy->getReturnType()) << " ("; for (FunctionType::ParamTypes::const_iterator @@ -903,7 +904,7 @@ o << " " << getType()->getDescription() << " "; - map TypeTable; + std::map TypeTable; WriteConstantInt(o, this, false, TypeTable, 0); } From lattner at cs.uiuc.edu Wed May 7 21:36:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:36:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/FunctionInlining.cpp Message-ID: <200305080235.VAA28557@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: FunctionInlining.cpp updated: 1.42 -> 1.43 --- Log message: Remove using decl --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/FunctionInlining.cpp diff -u llvm/lib/Transforms/IPO/FunctionInlining.cpp:1.42 llvm/lib/Transforms/IPO/FunctionInlining.cpp:1.43 --- llvm/lib/Transforms/IPO/FunctionInlining.cpp:1.42 Wed Apr 23 11:37:38 2003 +++ llvm/lib/Transforms/IPO/FunctionInlining.cpp Wed May 7 21:34:52 2003 @@ -25,7 +25,6 @@ #include static Statistic<> NumInlined("inline", "Number of functions inlined"); -using std::cerr; // InlineFunction - This function forcibly inlines the called function into the // basic block of the caller. This returns false if it is not possible to @@ -46,7 +45,7 @@ if (CalledFunc == 0 || // Can't inline external function or indirect call! CalledFunc->isExternal()) return false; - //cerr << "Inlining " << CalledFunc->getName() << " into " + //std::cerr << "Inlining " << CalledFunc->getName() << " into " // << CurrentMeth->getName() << "\n"; BasicBlock *OrigBB = CI->getParent(); From lattner at cs.uiuc.edu Wed May 7 21:37:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:37:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/FunctionInlining.cpp Message-ID: <200305080236.VAA28616@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: FunctionInlining.cpp updated: 1.43 -> 1.44 --- Log message: Don't inline functions that take variable numbers of arguments! --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/FunctionInlining.cpp diff -u llvm/lib/Transforms/IPO/FunctionInlining.cpp:1.43 llvm/lib/Transforms/IPO/FunctionInlining.cpp:1.44 --- llvm/lib/Transforms/IPO/FunctionInlining.cpp:1.43 Wed May 7 21:34:52 2003 +++ llvm/lib/Transforms/IPO/FunctionInlining.cpp Wed May 7 21:36:43 2003 @@ -20,7 +20,7 @@ #include "llvm/iTerminators.h" #include "llvm/iPHINode.h" #include "llvm/iOther.h" -#include "llvm/Type.h" +#include "llvm/DerivedTypes.h" #include "Support/Statistic.h" #include @@ -42,8 +42,9 @@ assert(CI->getParent()->getParent() && "Instruction not in function!"); const Function *CalledFunc = CI->getCalledFunction(); - if (CalledFunc == 0 || // Can't inline external function or indirect call! - CalledFunc->isExternal()) return false; + if (CalledFunc == 0 || // Can't inline external function or indirect + CalledFunc->isExternal() || // call, or call to a vararg function! + CalledFunc->getFunctionType()->isVarArg()) return false; //std::cerr << "Inlining " << CalledFunc->getName() << " into " // << CurrentMeth->getName() << "\n"; From lattner at cs.uiuc.edu Wed May 7 21:40:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:40:00 2003 Subject: [llvm-commits] CVS: llvm/test/Feature/varargs.ll Message-ID: <200305080239.VAA29131@apoc.cs.uiuc.edu> Changes in directory llvm/test/Feature: varargs.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: Index: llvm/test/Feature/varargs.ll diff -c /dev/null llvm/test/Feature/varargs.ll:1.1 *** /dev/null Wed May 7 21:39:47 2003 --- llvm/test/Feature/varargs.ll Wed May 7 21:39:37 2003 *************** *** 0 **** --- 1,9 ---- + + + + int %test(int %X, ...) { + %ap = alloca sbyte* + ; This is not a legal testcase, it just shows the syntax for va_arg + %tmp = va_arg sbyte** %ap, int + ret int %tmp + } From jstanley at cs.uiuc.edu Wed May 7 21:41:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Wed May 7 21:41:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/InstManip.h PhaseInfo.h Phases.cpp SparcInstManip.cpp SparcInstManip.h Message-ID: <200305080150.UAA14668@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib: InstManip.h updated: 1.14 -> 1.15 PhaseInfo.h updated: 1.1 -> 1.2 Phases.cpp updated: 1.23 -> 1.24 SparcInstManip.cpp updated: 1.3 -> 1.4 SparcInstManip.h updated: 1.4 -> 1.5 --- Log message: Cleaned up class design. Phase 5 slot is now being generated and branched to. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/InstManip.h diff -u llvm/lib/Reoptimizer/Inst/lib/InstManip.h:1.14 llvm/lib/Reoptimizer/Inst/lib/InstManip.h:1.15 --- llvm/lib/Reoptimizer/Inst/lib/InstManip.h:1.14 Wed Apr 30 14:21:06 2003 +++ llvm/lib/Reoptimizer/Inst/lib/InstManip.h Wed May 7 20:50:06 2003 @@ -29,9 +29,11 @@ class TraceCache; class Phase2; class Phase3; +class Phase4; class InstCandidate; class Phase3Info; class Phase4Info; +struct PrimInfo; class InstManip { @@ -58,14 +60,24 @@ // in this manner because there are not really enough phases to warrant building the // slot-building behavior into the Phase{3,4}Info classes themselves. + // For the phase 3 slot virtual void buildSlot(Phase3Info* p3info, std::vector& snippet) = 0; + // For the phase 4 slot virtual void buildSlot(Phase4Info* p4info, std::vector& snippet) = 0; + // For the phase 5 slot + virtual void buildSlot(PrimInfo* pi, + uint64_t slotBase, + uint64_t instAddr, + uint64_t startAddr, + std::vector& snippet) = 0; + virtual unsigned getSlotSize(Phase2* p2) const = 0; virtual unsigned getSlotSize(Phase3* p3, InstCandidate& cand) const = 0; + virtual unsigned getSlotSize(Phase4* p4) const = 0; // findCandidates - Build the vector of instruction candidates that occur in the // region defined by the given addresses. This is necessarily a platform-dependent Index: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h diff -u llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.1 llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.2 --- llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.1 Wed Apr 30 16:28:07 2003 +++ llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h Wed May 7 20:50:06 2003 @@ -15,6 +15,12 @@ typedef std::pair AddressRange; +typedef struct PrimInfo { + unsigned gbtType; + unsigned short* loadVar; + unsigned gbtStartIdx; +}; + class Phase3Info { public: @@ -70,11 +76,13 @@ { public: Phase4Info(const InstCandidate& candidate, + uint64_t startAddr, uint64_t slotDescriptor, uint64_t slotSize, TraceCache* pTC, InstManip* pIM): m_candidate(candidate), + m_startAddr(startAddr), m_slotDescriptor(slotDescriptor), m_slotSize(slotSize), m_pTC(pTC), @@ -83,6 +91,7 @@ } const InstCandidate& getCandidate() const { return m_candidate; } + uint64_t getStartAddr() const { return m_startAddr; } uint64_t getSlot() const { return m_slotDescriptor; } uint64_t getSlotSize() const { return m_slotSize; } TraceCache* getTraceCache() { return m_pTC; } @@ -92,11 +101,11 @@ Phase4Info() {} InstCandidate m_candidate; // Candidate responsible for this instance's creation + uint64_t m_startAddr; // Start address of enclosing function uint64_t m_slotDescriptor; // Slot created by phase 3 unsigned m_slotSize; // Size of slot created by phase 3 TraceCache* m_pTC; // TraceCache instance used by phases 2 and 3 InstManip* m_pIM; // The InstManip instance to pass to the next phase }; - #endif // _INCLUDED_PHASEINFO_H Index: llvm/lib/Reoptimizer/Inst/lib/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.23 llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.24 --- llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.23 Sun May 4 16:16:17 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phases.cpp Wed May 7 20:50:06 2003 @@ -66,6 +66,14 @@ #include "PhaseInfo.h" #include "SparcInstManip.h" +#define DEBUG 1 + +#if DEBUG +#define DEBUG_MSG(x) std::cerr << x << std::endl +#else +#define DEBUG_MSG(x) +#endif + using std::vector; using std::cerr; using std::endl; @@ -78,12 +86,6 @@ // obtained in the same manner. extern unsigned ppGBTSize; -typedef struct PrimInfo { - unsigned gbtType; - unsigned short* loadVar; - unsigned gbtStartIdx; -}; - extern PrimInfo ppGBT[]; typedef std::pair AddressRange; @@ -167,10 +169,10 @@ void Phase2::transform() { - cerr << "============================== Begin Phase 2 ==============================\n"; + DEBUG_MSG("============================== Begin Phase 2 =============================="); const char* execName = getexecname(); - cerr << "Executable name is: " << execName << endl; + DEBUG_MSG("Executable name is: " << execName); ElfReader elfReader(execName); @@ -185,7 +187,7 @@ while(elfReader.findNextSymbol(funcName, range, m_pIM->getInstWidth())) funcs.push_back(std::make_pair(funcName, range)); - cerr << "There are " << funcs.size() << " functions to process." << endl << endl; + DEBUG_MSG("There are " << funcs.size() << " functions to process." << endl); m_pIM->makePhase3SpillRegion(funcs.size()); @@ -197,13 +199,13 @@ //cerr << i->first << " is to be transformed" << endl; if(i->first == "fibs") { - cerr << "Transforming function " << i->first << "..." << endl; + DEBUG_MSG("Transforming function " << i->first << "..."); transformFunction(i->second); } } } - cerr << "============================== End Phase 2 ==============================\n"; + DEBUG_MSG("============================== End Phase 2 ==========================="); } @@ -234,6 +236,14 @@ return slotBase; } +static void dumpSnippet(vector& snippet, InstManip* im) +{ + for(vector::iterator j = snippet.begin(), k = snippet.end(); j != k; ++j) { + im->printInst(*j); + cerr << endl; + } +} + void Phase2::transformFunction(AddressRange& range) { // Obtain address of first replacable instruction in function and obtain a new slot @@ -260,12 +270,10 @@ vector snippet; m_pIM->buildSlot(p3info, snippet); - // Dump snippet instructions: - cerr << "phase3 slot instructions:" << endl; - for(vector::iterator j = snippet.begin(), k = snippet.end(); j != k; ++j) { - m_pIM->printInst(*j); - cerr << endl; - } +#if DEBUG + DEBUG_MSG("phase3 slot instructions:"); + dumpSnippet(snippet, m_pIM); +#endif // Copy the snippet code into the slot copySnippetToSlot(snippet, slotBase, vm, m_pIM); @@ -284,9 +292,9 @@ m_pTC(p3info->getTraceCache()), m_pIM(p3info->getIM()) { - cerr << "================ Begin Phase 3 [" << std::hex - << m_pPhase3Info->getStartAddr() << ", " << m_pPhase3Info->getEndAddr() - << "] ================\n"; + DEBUG_MSG("================ Begin Phase 3 [" << std::hex + << m_pPhase3Info->getStartAddr() << ", " << m_pPhase3Info->getEndAddr() + << "] ================"); // 1. Replace the original (replaced) instruction at the proper location in the // original code (thus effectively removing the branch to the slot created by phase 2 @@ -318,8 +326,10 @@ // For each load candidate, obtain a new slot and write the phase 4 slot region // contents into it. + DEBUG_MSG("There are " << candidates.size() << " candidates to process"); + for(vector::iterator i = candidates.begin(), e = candidates.end(); i != e; ++i) { - cerr << "Transforming " << *i << endl; + DEBUG_MSG("Transforming " << *i); unsigned slotSize = m_pIM->getSlotSize(this, *i); // Replace load candidate instruction with a branch to the start of a new slot. @@ -328,17 +338,16 @@ // Build the Phase4Info structure and generate the phase 4 slot. - Phase4Info* p4info = new Phase4Info(*i, slotBase, slotSize, m_pTC, m_pIM); + Phase4Info* p4info = new Phase4Info(*i, m_pPhase3Info->getStartAddr(), + slotBase, slotSize, m_pTC, m_pIM); vector snippet; m_pIM->buildSlot(p4info, snippet); - // Dump snippet instructions: - cerr << "phase4 slot instructions:" << endl; - for(vector::iterator j = snippet.begin(), k = snippet.end(); j != k; ++j) { - m_pIM->printInst(*j); - cerr << endl; - } +#if DEBUG + DEBUG_MSG("phase4 slot instructions:"); + dumpSnippet(snippet, m_pIM); +#endif // Copy the snippet code into the slot copySnippetToSlot(snippet, slotBase, m_pTC->getVM(), m_pIM); @@ -358,14 +367,13 @@ // ...and process them processCandidates(candidates); - cerr << "============================== End Phase 3 ==============================\n"; + DEBUG_MSG("============================== End Phase 3 =============================="); } //////////////// Phase4 implementation //////////////// void phase4(uint64_t tag, Phase4Info* p4info) { - cerr << "phase 4 fcn, tag is " << tag << endl; Phase4 p4(tag, p4info); p4.transform(); } @@ -376,8 +384,7 @@ m_pIM(p4info->getIM()), m_tag(tag) { - cerr << "phase4 ctor: tag is " << tag << endl; - cerr << "================ Begin Phase 4 ================\n"; + DEBUG_MSG("================ Begin Phase 4 ================"); } Phase4::~Phase4() @@ -420,39 +427,47 @@ return 0; } -void fakeInstFunc(double* param) -{ - cerr << "I AM AN INSTRUMENTATION FUNCTION, FEAR ME!" << endl; - *param = 3.14; -} - void Phase4::transform() { - cerr << "tag is " << m_tag << endl; + +#if DEBUG + DEBUG_MSG("tag is " << m_tag); dumpGBT(cerr); +#endif if(PrimInfo* pi = searchGBT(m_tag)) { - cerr << "Tag matches." << endl; + DEBUG_MSG("Tag matches."); const InstCandidate& cand = m_pPhase4Info->getCandidate(); -#if 0 - // Make a new slot that calls the instrumentation function, inserting a branch to - // it over the original code. - - uint64_t slotBase = replaceInstWithBrToSlot(cand.front().first, getSlotSize(), - m_pTC, m_instManip); -#endif + assert(cand.getInsts().size() >= 2 + && "Unexpected number of instructions in candidate"); // Write NOPs over the original instructions that were associated with the elected - // candidate, but leave the branch instruction intact. + // candidate. No need to no-op over the candidate load instruction itself since + // we're about to write over it with a branch to the phase 5 slot. VirtualMem* vm = m_pTC->getVM(); for(vector >::const_iterator i = cand.getInsts().begin() + 1, e = cand.getInsts().end(); i != e; ++i) vm->writeInstToVM(i->first, m_pIM->getNOP()); - // Write the instructions to call the instrumentation function + // Obtain memory (& rewrite branch) to the phase 5 slot. + + unsigned slotSize = m_pIM->getSlotSize(this); + uint64_t repAddr = cand.front().first; + uint64_t slotBase = replaceInstWithBrToSlot(repAddr, slotSize, m_pTC, m_pIM); + vector snippet; + m_pIM->buildSlot(pi, slotBase, repAddr, m_pPhase4Info->getStartAddr(), snippet); + +#if DEBUG + DEBUG_MSG("phase 5 slot contents: "); + dumpSnippet(snippet, m_pIM); +#endif + + copySnippetToSlot(snippet, slotBase, m_pTC->getVM(), m_pIM); + +#if 0 void* instFuncVP = (void*) fakeInstFunc; // From the GBT eventually void (*instFunc)(void*) = (void (*)(void*)) instFuncVP; @@ -460,9 +475,11 @@ instFunc(mem); printf("%f\n", *((double*) mem)); free(mem); + +#endif } else { - cerr << "Could not find tag" << endl; + DEBUG_MSG("Could not find tag"); // The candidate failed to get elected, so pack up and go home. Restore the // replaced instruction (i.e. the branch that invoked this code) with the original // instruction at that location. @@ -472,11 +489,20 @@ m_pPhase4Info->getCandidate().front().second); } +#if 0 // (TEMP) For now, restore the candidate load to its original position for debugging // purposes. m_pPhase4Info->getTraceCache()->getVM()->writeInstToVM(m_pPhase4Info->getCandidate().front().first, m_pPhase4Info->getCandidate().front().second); +#endif + + DEBUG_MSG("================ End Phase 4 ================"); +} - cerr << "================ End Phase 4 ================\n"; +//////////////// Phase 5 implementation //////////////// + +void phase5(PrimInfo* pi) +{ + DEBUG_MSG("phase5 function invoked"); } Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.3 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.4 --- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.3 Wed Apr 30 12:31:47 2003 +++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp Wed May 7 20:50:06 2003 @@ -47,10 +47,10 @@ #include "SparcInstManip.h" #include "PhaseInfo.h" +// These are exported due to some inline methods in SparcInstManip.h +uint64_t SparcInstManip::sm_phase4SpillRegion[SparcInstManip::SHARED_SIZE]; const unsigned SparcInstManip::BRANCH_ALWAYS_BASE = 0x10480000; const unsigned SparcInstManip::BRANCH_ALWAYS_BASE_ANNUL = 0x30480000; -const unsigned SparcInstManip::BIAS = 2047; -uint64_t SparcInstManip::sm_phase4SpillRegion[SparcInstManip::SHARED_SIZE]; using std::cout; using std::cerr; @@ -59,6 +59,7 @@ void phase3(Phase3Info* p3info); void phase4(uint64_t tag, Phase4Info* p4info); +void phase5(PrimInfo* pi); SparcInstManip::SparcInstManip(TraceCache* tc): InstManip(tc, SHARED_SIZE, INST_WIDTH, NOP_INST), @@ -149,6 +150,35 @@ "Snippet size does not match expected slot size"); } +void SparcInstManip::buildSlot(PrimInfo* pi, + uint64_t slotBase, + uint64_t instAddr, + uint64_t startAddr, + std::vector& snippet) +{ + // Before we generate code to spill the shared registers, we must first search + // backwards from the instrumentation site (i.e., the branch to the slot, formerly the + // load-volatile) to discover a marker alloca that will tell us the correct offset in + // the current stack frame. startAddr is the starting address of the function + // containing the instrumentation site. We will search backwards from instAddr for a + // valid alloca marker, stopping at startAddr if we do not encounter one. + + unsigned offset = findAllocaOffset(instAddr, startAddr); + + startCode(snippet); + + generateSave(); + generateCall((uint64_t) &phase5, slotBase); + + // We need to branch back to one instruction beyond instruction that branches to the + // phase 5 slot. + generateBranchAlways(instAddr + getInstWidth(), slotBase, getRestoreInst()); + + endCode(); + + // TODO: Add assert against against the snippet. +} + unsigned SparcInstManip::getSlotSize(Phase2* p2) const { // The following sum corresponds to the sizes consumed by the various regions of the @@ -157,12 +187,12 @@ (void) p2; - return getGenSaveSize() + - getGenSpillSharedSize() + - getGenLoadSize() + - getGenCallSize() + - getGenRestoreSharedSize() + - getGenBranchAlwaysSize(); + return GEN_SAVE_SIZE + + GEN_SPL_SHARED_SIZE + + GEN_LOAD_SIZE + + GEN_CALL_SIZE + + GEN_RESTR_SHARED_SIZE + + GEN_BRANCH_ALWAYS_SIZE; } unsigned SparcInstManip::getSlotSize(Phase3* p3, InstCandidate& cand) const @@ -173,15 +203,26 @@ (void) p3; - return getGenSaveSize() + + return GEN_SAVE_SIZE + getGenAddressCopySize(cand.front().second) + - getGenParamStoreSize() + - getGenSpillSharedSize() + - getGenLoadSize() + - getGenParamStoreSize() + - getGenCallSize() + - getGenRestoreSharedSize() + - getGenBranchAlwaysSize(); + GEN_PSTORE_SIZE + + GEN_SPL_SHARED_SIZE + + GEN_LOAD_SIZE + + GEN_PSTORE_SIZE + + GEN_CALL_SIZE + + GEN_RESTR_SHARED_SIZE + + GEN_BRANCH_ALWAYS_SIZE; +} + +unsigned SparcInstManip::getSlotSize(Phase4* p4) const +{ + // The following sum corresponds to the sizes consumed by the various regions of the + // the slot constructed by phase 4, called the phase 5 slot. See ASCII diagram of + // phase 5 slot contents for details. + + (void) p4; + + return GEN_SAVE_SIZE + GEN_CALL_SIZE + GEN_BRANCH_ALWAYS_SIZE; } void SparcInstManip::findCandidates(uint64_t start, @@ -233,8 +274,8 @@ } void SparcInstManip::generateLoad(uint64_t value, - LogicalRegister dest, - LogicalRegister tmp) + LogicalRegister dest, + LogicalRegister tmp) { // When reg == REG_0, load the 64-bit value into %o0, using %o0 and %o1. // When reg == REG_1, load the 64-bit value into %o1, using %o1 and %o2. @@ -266,13 +307,13 @@ // add %destReg, (lwr 10b of lwr wrd), %destReg snippet.push_back(MK_ADD_R_I(destReg, destReg, LOW10(LOWWORD(value)))); - assert(snippet.size() - initSize == getGenLoadSize() && + assert(snippet.size() - initSize == GEN_LOAD_SIZE && "Unexpected number of instructions in code sequence for 64-bit value -> %dest"); } void SparcInstManip::generateAddressCopy(unsigned loadInst, - LogicalRegister dest, - bool afterSave) + LogicalRegister dest, + bool afterSave) { // NB: After save instruction has been issued, the output registers are mapped to the // input registers. @@ -317,7 +358,7 @@ snippet.push_back(MK_STX_STACK(srcReg, BIAS + off)); - assert(snippet.size() - initSize == getGenParamStoreSize() && + assert(snippet.size() - initSize == GEN_PSTORE_SIZE && "Unexpected number of instructions in code sequence for parameter store"); } @@ -336,7 +377,7 @@ snippet.push_back(getCallInst(dest, callInstAddr)); snippet.push_back(getNOP()); - assert(snippet.size() - initSize == getGenCallSize() && + assert(snippet.size() - initSize == GEN_CALL_SIZE && "Unexpected number of instructions in code sequence for call"); } @@ -355,7 +396,7 @@ snippet.push_back(getRestoreInst()); - assert(snippet.size() - initSize == getGenRestoreSize() && + assert(snippet.size() - initSize == GEN_RESTORE_SIZE && "Unexpected number of instructions in code sequence for restore"); } @@ -369,7 +410,7 @@ // save %sp, -176, %sp snippet.push_back(MK_SAVE_IMM(R_O6, R_O6, -176)); - assert(snippet.size() - initSize == getGenSaveSize() && + assert(snippet.size() - initSize == GEN_SAVE_SIZE && "Unexpected number of instructions in code sequence for save"); } @@ -377,8 +418,8 @@ // shared registers instead of dumping all of the code into the current snippet. void SparcInstManip::generateRestoreShared(uint64_t restoreFromAddr, - LogicalRegister tmp1, - LogicalRegister tmp2) + LogicalRegister tmp1, + LogicalRegister tmp2) { assert(m_pCurrSnippet && "Invalid snippet for code generation"); assert(tmp1 != tmp2 && "Distinct logical registers required"); @@ -396,13 +437,13 @@ snippet.push_back(MK_LOAD_IMM(R_G6, tmpReg, 48)); snippet.push_back(MK_LOAD_IMM(R_G7, tmpReg, 56)); - assert(snippet.size() - initSize == getGenRestoreSharedSize() && + assert(snippet.size() - initSize == GEN_RESTR_SHARED_SIZE && "Unexpected number of instructions in code sequence for restore shared"); } void SparcInstManip::generateSpillShared(uint64_t spillToAddr, - LogicalRegister tmp1, - LogicalRegister tmp2) + LogicalRegister tmp1, + LogicalRegister tmp2) { assert(m_pCurrSnippet && "Invalid snippet for code generation"); assert(tmp1 != tmp2 && "Distinct logical registers required"); @@ -420,13 +461,13 @@ snippet.push_back(MK_STORE_IMM(R_G6, tmpReg, 48)); snippet.push_back(MK_STORE_IMM(R_G7, tmpReg, 56)); - assert(snippet.size() - initSize == getGenSpillSharedSize() && + assert(snippet.size() - initSize == GEN_SPL_SHARED_SIZE && "Unexpected number of instructions in code sequence for spill shared"); } void SparcInstManip::generateBranchAlways(uint64_t dest, - uint64_t slotBase, - unsigned delaySlotInstr) + uint64_t slotBase, + unsigned delaySlotInstr) { assert(m_pCurrSnippet && "Invalid snippet for code generation"); vector& snippet = *m_pCurrSnippet; @@ -440,7 +481,7 @@ snippet.push_back(getBranchAlways(dest, branchInstAddr, false)); // annul bit low snippet.push_back(delaySlotInstr); - assert(snippet.size() - initSize == getGenBranchAlwaysSize() && + assert(snippet.size() - initSize == GEN_BRANCH_ALWAYS_SIZE && "Unexpected number of instruction in code sequence for branch-always"); } @@ -646,5 +687,10 @@ return currAddr; } + return 0; +} + +unsigned SparcInstManip::findAllocaOffset(uint64_t instAddr, uint64_t startAddr) +{ return 0; } Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.4 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.5 --- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.4 Wed Apr 30 12:37:10 2003 +++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h Wed May 7 20:50:06 2003 @@ -31,8 +31,15 @@ virtual void buildSlot(Phase4Info* p3info, std::vector& snippet); + virtual void buildSlot(PrimInfo* pi, + uint64_t slotBase, + uint64_t instAddr, + uint64_t startAddr, + std::vector& snippet); + virtual unsigned getSlotSize(Phase2* p2) const; virtual unsigned getSlotSize(Phase3* p3, InstCandidate& cand) const; + virtual unsigned getSlotSize(Phase4* p4) const; virtual void findCandidates(uint64_t start, uint64_t end, @@ -80,19 +87,6 @@ unsigned getRestoreInst() const; inline unsigned getCallInst(uint64_t dest, uint64_t pc) const; - - // These need to become class constants where possible since this portion of the - // interface is no longer externally visible and they never became virtual functions - // as intended. TODO. - - unsigned getGenLoadSize() const { return 6; } - unsigned getGenCallSize() const { return 2; } - unsigned getGenBranchAlwaysSize() const { return 2; } - unsigned getGenSaveSize() const { return 1; } - unsigned getGenParamStoreSize() const { return 1; } - unsigned getGenSpillSharedSize() const { return getGenLoadSize() + getSharedSize(); } - unsigned getGenRestoreSharedSize() const { return getGenLoadSize() + getSharedSize(); } - unsigned getGenRestoreSize() const { return 1; } inline unsigned getGenAddressCopySize(unsigned loadInst) const; uint64_t getPhase4SpillAddr() { return (uint64_t) sm_phase4SpillRegion; } @@ -113,35 +107,43 @@ uint64_t findNextStackLoad(uint64_t addr, uint64_t end, unsigned fpOffset); + + unsigned findAllocaOffset(uint64_t instAddr, uint64_t startAddr); std::vector* m_pCurrSnippet; OutputToInputRegMap m_outputToInputReg; // Maps input register -> output register - // Branch-always (annul bit high) instruction base (i.e., address not filled in yet) - static const unsigned BRANCH_ALWAYS_BASE_ANNUL; - - // Branch-always (annul bit low) instruction base (i.e., address not filled in yet) - static const unsigned BRANCH_ALWAYS_BASE; - - // NOP instruction for SparcV9 - static const unsigned NOP_INST = 0x01000000; - // Size (in number of 64-bit words) required for storing shared registers static const unsigned SHARED_SIZE = 7; - // Instruction width (in bytes) - static const unsigned INST_WIDTH = 4; - - // Sparc-specific constant used in SP manipulations - static const unsigned BIAS; - - // Memory region into which to spill shared registers when executing a phase 4 slot - // (i.e., the slot that invokes the phase4 function, the slot written by phase 3 + // The memory region into which to spill shared registers when executing a phase 4 + // slot (i.e., the slot that invokes the phase4 function, the slot written by phase 3 // invocations). NB: One region is sufficient and we do not need stack semantics // because only one activation of a phase 4 slot ever occurs at a given time (assuming // single-threaded execution). - static uint64_t sm_phase4SpillRegion[SHARED_SIZE]; + static uint64_t sm_phase4SpillRegion[SHARED_SIZE]; + + // Branch-always (annul bit high) instruction base (address not filled in yet) + static const unsigned BRANCH_ALWAYS_BASE_ANNUL; + + // Branch-always (annul bit low) instruction base (address not filled in yet) + static const unsigned BRANCH_ALWAYS_BASE; + + static const unsigned INST_WIDTH = 4; // In bytes + static const unsigned NOP_INST = 0x01000000; + static const unsigned BIAS = 2047; + + // Fixed sizes of generated SparcV9 assembly snippets + + static const unsigned GEN_LOAD_SIZE = 6; + static const unsigned GEN_CALL_SIZE = 2; + static const unsigned GEN_BRANCH_ALWAYS_SIZE = 2; + static const unsigned GEN_SAVE_SIZE = 1; + static const unsigned GEN_PSTORE_SIZE = 1; + static const unsigned GEN_RESTORE_SIZE = 1; + static const unsigned GEN_SPL_SHARED_SIZE = GEN_LOAD_SIZE + SHARED_SIZE; + static const unsigned GEN_RESTR_SHARED_SIZE = GEN_SPL_SHARED_SIZE; }; unsigned SparcInstManip::getBranchAlways(uint64_t dest, uint64_t pc, bool annul) const From lattner at cs.uiuc.edu Wed May 7 21:42:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:42:00 2003 Subject: [llvm-commits] CVS: llvm/utils/emacs/llvm-mode.el Message-ID: <200305080241.VAA29587@apoc.cs.uiuc.edu> Changes in directory llvm/utils/emacs: llvm-mode.el updated: 1.3 -> 1.4 --- Log message: Add support for new va_arg instruction --- Diffs of the changes: Index: llvm/utils/emacs/llvm-mode.el diff -u llvm/utils/emacs/llvm-mode.el:1.3 llvm/utils/emacs/llvm-mode.el:1.4 --- llvm/utils/emacs/llvm-mode.el:1.3 Tue Apr 22 14:31:55 2003 +++ llvm/utils/emacs/llvm-mode.el Wed May 7 21:41:08 2003 @@ -34,7 +34,7 @@ ;; Arithmetic and Logical Operators '("add\\|sub\\|mul\\|div\\|rem\\|and\\|or\\|xor\\|set\\(ne\\|eq\\|lt\\|gt\\|le\\|ge\\)" . font-lock-keyword-face) ;; Special instructions - '("phi\\|call\\|cast\\|shl\\|shr" . font-lock-keyword-face) + '("phi\\|call\\|cast\\|shl\\|shr\\|va_arg" . font-lock-keyword-face) ;; Control instructions '("ret\\|br\\|switch\\|invoke" . font-lock-keyword-face) ;; Memory operators From lattner at cs.uiuc.edu Wed May 7 21:42:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:42:02 2003 Subject: [llvm-commits] CVS: llvm/utils/vim/llvm.vim Message-ID: <200305080241.VAA29601@apoc.cs.uiuc.edu> Changes in directory llvm/utils/vim: llvm.vim updated: 1.3 -> 1.4 --- Log message: Add support for new va_arg instruction --- Diffs of the changes: Index: llvm/utils/vim/llvm.vim diff -u llvm/utils/vim/llvm.vim:1.3 llvm/utils/vim/llvm.vim:1.4 --- llvm/utils/vim/llvm.vim:1.3 Tue Apr 22 14:31:53 2003 +++ llvm/utils/vim/llvm.vim Wed May 7 21:41:11 2003 @@ -20,7 +20,7 @@ syn keyword llvmStatement and or xor syn keyword llvmStatement setne seteq setlt setgt setle setge -syn keyword llvmStatement phi call cast shl shr +syn keyword llvmStatement phi call cast shl shr va_arg syn keyword llvmStatement ret br switch invoke syn keyword llvmStatement malloc alloca free load store getelementptr From lattner at cs.uiuc.edu Wed May 7 21:44:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:44:00 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Support/InstVisitor.h Message-ID: <200305080243.VAA29894@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Support: InstVisitor.h updated: 1.14 -> 1.15 --- Log message: Add support for the new VarArgInst instruction, reindent some stuff --- Diffs of the changes: Index: llvm/include/llvm/Support/InstVisitor.h diff -u llvm/include/llvm/Support/InstVisitor.h:1.14 llvm/include/llvm/Support/InstVisitor.h:1.15 --- llvm/include/llvm/Support/InstVisitor.h:1.14 Tue Sep 10 10:35:23 2002 +++ llvm/include/llvm/Support/InstVisitor.h Wed May 7 21:43:06 2003 @@ -148,6 +148,7 @@ RetTy visitCall(CallInst &I) { DELEGATE(CallInst); } RetTy visitShr(ShiftInst &I) { DELEGATE(ShiftInst); } RetTy visitShl(ShiftInst &I) { DELEGATE(ShiftInst); } + RetTy visitVarArg(VarArgInst &I) { DELEGATE(VarArgInst); } RetTy visitUserOp1(Instruction &I) { DELEGATE(Instruction); } RetTy visitUserOp2(Instruction &I) { DELEGATE(Instruction); } @@ -162,14 +163,15 @@ RetTy visitSetCondInst(SetCondInst &I) { DELEGATE(BinaryOperator);} RetTy visitMallocInst(MallocInst &I) { DELEGATE(AllocationInst);} RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(AllocationInst);} - RetTy visitFreeInst(FreeInst &I) { DELEGATE(Instruction); } - RetTy visitLoadInst(LoadInst &I) { DELEGATE(Instruction); } - RetTy visitStoreInst(StoreInst &I) { DELEGATE(Instruction); } + RetTy visitFreeInst(FreeInst &I) { DELEGATE(Instruction); } + RetTy visitLoadInst(LoadInst &I) { DELEGATE(Instruction); } + RetTy visitStoreInst(StoreInst &I) { DELEGATE(Instruction); } RetTy visitGetElementPtrInst(GetElementPtrInst &I){ DELEGATE(Instruction); } - RetTy visitPHINode(PHINode &I) { DELEGATE(Instruction); } - RetTy visitCastInst(CastInst &I) { DELEGATE(Instruction); } - RetTy visitCallInst(CallInst &I) { DELEGATE(Instruction); } - RetTy visitShiftInst(ShiftInst &I) { DELEGATE(Instruction); } + RetTy visitPHINode(PHINode &I) { DELEGATE(Instruction); } + RetTy visitCastInst(CastInst &I) { DELEGATE(Instruction); } + RetTy visitCallInst(CallInst &I) { DELEGATE(Instruction); } + RetTy visitShiftInst(ShiftInst &I) { DELEGATE(Instruction); } + RetTy visitVarArgInst(VarArgInst &I) { DELEGATE(Instruction); } // Next level propogators... if the user does not overload a specific // instruction type, they can overload one of these to get the whole class From lattner at cs.uiuc.edu Wed May 7 21:44:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:44:02 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Instruction.def iOther.h Message-ID: <200305080243.VAA29901@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Instruction.def updated: 1.5 -> 1.6 iOther.h updated: 1.32 -> 1.33 --- Log message: Add new VarArgInst class for the va_arg instruction --- Diffs of the changes: Index: llvm/include/llvm/Instruction.def diff -u llvm/include/llvm/Instruction.def:1.5 llvm/include/llvm/Instruction.def:1.6 --- llvm/include/llvm/Instruction.def:1.5 Tue Sep 10 10:27:31 2002 +++ llvm/include/llvm/Instruction.def Wed May 7 21:42:50 2003 @@ -119,10 +119,11 @@ HANDLE_OTHER_INST(29, Shl , ShiftInst ) // Shift operations HANDLE_OTHER_INST(30, Shr , ShiftInst ) +HANDLE_OTHER_INST(31, VarArg , VarArgInst ) // va_arg instruction -HANDLE_OTHER_INST(31, UserOp1, Instruction) // May be used internally in a pass -HANDLE_OTHER_INST(32, UserOp2, Instruction) - LAST_OTHER_INST(32) +HANDLE_OTHER_INST(32, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(33, UserOp2, Instruction) + LAST_OTHER_INST(33) #undef FIRST_TERM_INST #undef HANDLE_TERM_INST Index: llvm/include/llvm/iOther.h diff -u llvm/include/llvm/iOther.h:1.32 llvm/include/llvm/iOther.h:1.33 --- llvm/include/llvm/iOther.h:1.32 Mon Feb 24 14:48:28 2003 +++ llvm/include/llvm/iOther.h Wed May 7 21:42:50 2003 @@ -121,4 +121,40 @@ } }; + +//===----------------------------------------------------------------------===// +// VarArgInst Class +//===----------------------------------------------------------------------===// + +/// VarArgInst - This class represents the va_arg llvm instruction, which reads +/// an argument of the destination type from the va_list operand pointed to by +/// the only operand. +/// +class VarArgInst : public Instruction { + VarArgInst(const VarArgInst &VAI) : Instruction(VAI.getType(), VarArg) { + Operands.reserve(1); + Operands.push_back(Use(VAI.Operands[0], this)); + } +public: + VarArgInst(Value *S, const Type *Ty, const std::string &Name = "", + Instruction *InsertBefore = 0) + : Instruction(Ty, VarArg, Name, InsertBefore) { + Operands.reserve(1); + Operands.push_back(Use(S, this)); + } + + virtual Instruction *clone() const { return new VarArgInst(*this); } + + bool mayWriteToMemory() const { return true; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const VarArgInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == VarArg; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + #endif From lattner at cs.uiuc.edu Wed May 7 21:45:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:45:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Reader/ReadInst.cpp Message-ID: <200305080244.VAA29934@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Reader: ReadInst.cpp updated: 1.40 -> 1.41 --- Log message: Add support for the new va_arg instruction --- Diffs of the changes: Index: llvm/lib/Bytecode/Reader/ReadInst.cpp diff -u llvm/lib/Bytecode/Reader/ReadInst.cpp:1.40 llvm/lib/Bytecode/Reader/ReadInst.cpp:1.41 --- llvm/lib/Bytecode/Reader/ReadInst.cpp:1.40 Thu Mar 6 10:32:25 2003 +++ llvm/lib/Bytecode/Reader/ReadInst.cpp Wed May 7 21:44:04 2003 @@ -130,11 +130,15 @@ Value *V; switch (Raw.Opcode) { + case Instruction::VarArg: case Instruction::Cast: { V = getValue(Raw.Ty, Raw.Arg1); const Type *Ty = getType(Raw.Arg2); if (V == 0 || Ty == 0) { std::cerr << "Invalid cast!\n"; return true; } - Res = new CastInst(V, Ty); + if (Raw.Opcode == Instruction::Cast) + Res = new CastInst(V, Ty); + else + Res = new VarArgInst(V, Ty); return false; } case Instruction::PHINode: { From lattner at cs.uiuc.edu Wed May 7 21:45:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:45:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Writer/WriteInst.cpp Message-ID: <200305080244.VAA29941@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Writer: WriteInst.cpp updated: 1.27 -> 1.28 --- Log message: Add support for the new va_arg instruction --- Diffs of the changes: Index: llvm/lib/Bytecode/Writer/WriteInst.cpp diff -u llvm/lib/Bytecode/Writer/WriteInst.cpp:1.27 llvm/lib/Bytecode/Writer/WriteInst.cpp:1.28 --- llvm/lib/Bytecode/Writer/WriteInst.cpp:1.27 Tue Jan 21 14:13:49 2003 +++ llvm/lib/Bytecode/Writer/WriteInst.cpp Wed May 7 21:44:07 2003 @@ -35,7 +35,7 @@ output_vbr(Type, Out); // Result type unsigned NumArgs = I->getNumOperands(); - output_vbr(NumArgs + isa(I), Out); + output_vbr(NumArgs + (isa(I) || isa(I)), Out); for (unsigned i = 0; i < NumArgs; ++i) { int Slot = Table.getValSlot(I->getOperand(i)); @@ -43,9 +43,9 @@ output_vbr((unsigned)Slot, Out); } - if (isa(I)) { + if (isa(I) || isa(I)) { int Slot = Table.getValSlot(I->getType()); - assert(Slot != -1 && "Cast return type unknown?"); + assert(Slot != -1 && "Cast/VarArg return type unknown?"); output_vbr((unsigned)Slot, Out); } @@ -218,7 +218,7 @@ if (Slot > MaxOpSlot) MaxOpSlot = Slot; // Handle the special case for cast... - if (isa(I)) { + if (isa(I) || isa(I)) { // Cast has to encode the destination type as the second argument in the // packet, or else we won't know what type to cast to! Slots[1] = Table.getValSlot(I.getType()); From lattner at cs.uiuc.edu Wed May 7 21:45:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:45:04 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/AsmWriter.cpp Instruction.cpp Verifier.cpp Message-ID: <200305080244.VAA29952@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: AsmWriter.cpp updated: 1.85 -> 1.86 Instruction.cpp updated: 1.21 -> 1.22 Verifier.cpp updated: 1.46 -> 1.47 --- Log message: Add support for the new va_arg instruction --- Diffs of the changes: Index: llvm/lib/VMCore/AsmWriter.cpp diff -u llvm/lib/VMCore/AsmWriter.cpp:1.85 llvm/lib/VMCore/AsmWriter.cpp:1.86 --- llvm/lib/VMCore/AsmWriter.cpp:1.85 Wed May 7 21:08:14 2003 +++ llvm/lib/VMCore/AsmWriter.cpp Wed May 7 21:44:12 2003 @@ -3,8 +3,7 @@ // This library implements the functionality defined in llvm/Assembly/Writer.h // // Note that these routines must be extremely tolerant of various errors in the -// LLVM code, because of of the primary uses of it is for debugging -// transformations. +// LLVM code, because it can be used for debugging transformations. // //===----------------------------------------------------------------------===// @@ -814,8 +813,12 @@ writeOperand(AI->getArraySize(), true); } } else if (isa(I)) { - if (Operand) writeOperand(Operand, true); + writeOperand(Operand, true); Out << " to "; + printType(I.getType()); + } else if (isa(I)) { + writeOperand(Operand, true); + Out << ", "; printType(I.getType()); } else if (Operand) { // Print the normal way... Index: llvm/lib/VMCore/Instruction.cpp diff -u llvm/lib/VMCore/Instruction.cpp:1.21 llvm/lib/VMCore/Instruction.cpp:1.22 --- llvm/lib/VMCore/Instruction.cpp:1.21 Wed Nov 20 12:33:41 2002 +++ llvm/lib/VMCore/Instruction.cpp Wed May 7 21:44:12 2003 @@ -91,7 +91,8 @@ case Call: return "call"; case Shl: return "shl"; case Shr: return "shr"; - + case VarArg: return "va_arg"; + default: return " "; } Index: llvm/lib/VMCore/Verifier.cpp diff -u llvm/lib/VMCore/Verifier.cpp:1.46 llvm/lib/VMCore/Verifier.cpp:1.47 --- llvm/lib/VMCore/Verifier.cpp:1.46 Fri Apr 18 19:50:37 2003 +++ llvm/lib/VMCore/Verifier.cpp Wed May 7 21:44:12 2003 @@ -130,6 +130,7 @@ void visitPHINode(PHINode &PN); void visitBinaryOperator(BinaryOperator &B); void visitShiftInst(ShiftInst &SI); + void visitVarArgInst(VarArgInst &VAI); void visitCallInst(CallInst &CI); void visitGetElementPtrInst(GetElementPtrInst &GEP); void visitLoadInst(LoadInst &LI); @@ -402,7 +403,12 @@ visitInstruction(SI); } - +void Verifier::visitVarArgInst(VarArgInst &VAI) { + Assert1(VAI.getParent()->getParent()->getFunctionType()->isVarArg(), + "va_arg instruction may only occur in function with variable args!", + &VAI); + visitInstruction(VAI); +} void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { const Type *ElTy = From lattner at cs.uiuc.edu Wed May 7 21:45:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:45:06 2003 Subject: [llvm-commits] CVS: llvm/lib/AsmParser/Lexer.l llvmAsmParser.y Message-ID: <200305080244.VAA29968@apoc.cs.uiuc.edu> Changes in directory llvm/lib/AsmParser: Lexer.l updated: 1.33 -> 1.34 llvmAsmParser.y updated: 1.109 -> 1.110 --- Log message: Add support for the new va_arg instruction --- Diffs of the changes: Index: llvm/lib/AsmParser/Lexer.l diff -u llvm/lib/AsmParser/Lexer.l:1.33 llvm/lib/AsmParser/Lexer.l:1.34 --- llvm/lib/AsmParser/Lexer.l:1.33 Tue Apr 22 15:20:28 2003 +++ llvm/lib/AsmParser/Lexer.l Wed May 7 21:44:01 2003 @@ -221,6 +221,7 @@ cast { RET_TOK(OtherOpVal, Cast, CAST); } shl { RET_TOK(OtherOpVal, Shl, SHL); } shr { RET_TOK(OtherOpVal, Shr, SHR); } +va_arg { RET_TOK(OtherOpVal, VarArg, VA_ARG); } ret { RET_TOK(TermOpVal, Ret, RET); } br { RET_TOK(TermOpVal, Br, BR); } Index: llvm/lib/AsmParser/llvmAsmParser.y diff -u llvm/lib/AsmParser/llvmAsmParser.y:1.109 llvm/lib/AsmParser/llvmAsmParser.y:1.110 --- llvm/lib/AsmParser/llvmAsmParser.y:1.109 Fri Apr 25 16:47:33 2003 +++ llvm/lib/AsmParser/llvmAsmParser.y Wed May 7 21:44:01 2003 @@ -720,7 +720,7 @@ // Other Operators %type ShiftOps -%token PHI CALL INVOKE CAST SHL SHR +%token PHI CALL INVOKE CAST SHL SHR VA_ARG %start Module %% @@ -1612,6 +1612,10 @@ } | CAST ResolvedVal TO Types { $$ = new CastInst($2, *$4); + delete $4; + } + | VA_ARG ResolvedVal ',' Types { + $$ = new VarArgInst($2, *$4); delete $4; } | PHI PHIList { From lattner at cs.uiuc.edu Wed May 7 21:51:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 21:51:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/SCCP.cpp Message-ID: <200305080250.VAA30133@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: SCCP.cpp updated: 1.67 -> 1.68 --- Log message: Handle va_arg instruction correctly --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/SCCP.cpp diff -u llvm/lib/Transforms/Scalar/SCCP.cpp:1.67 llvm/lib/Transforms/Scalar/SCCP.cpp:1.68 --- llvm/lib/Transforms/Scalar/SCCP.cpp:1.67 Thu Apr 24 22:35:10 2003 +++ llvm/lib/Transforms/Scalar/SCCP.cpp Wed May 7 21:50:13 2003 @@ -193,6 +193,7 @@ void visitCallInst (Instruction &I) { markOverdefined(&I); } void visitInvokeInst (Instruction &I) { markOverdefined(&I); } void visitAllocationInst(Instruction &I) { markOverdefined(&I); } + void visitVarArgInst (Instruction &I) { markOverdefined(&I); } void visitFreeInst (Instruction &I) { /*returns void*/ } void visitInstruction(Instruction &I) { From lattner at cs.uiuc.edu Wed May 7 22:16:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 22:16:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Message-ID: <200305080315.WAA32189@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource/UnitTests: 2003-05-07-VarArgs.c updated: 1.1 -> 1.2 --- Log message: Add a test for va_copy as well --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c diff -u llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.1 llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.2 --- llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.1 Wed May 7 16:39:47 2003 +++ llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Wed May 7 22:15:31 2003 @@ -2,11 +2,15 @@ #include void test(char *fmt, ...) { - va_list ap; + va_list ap, aq; int d; - char c, *p, *s; + char c, *s; va_start(ap, fmt); + + va_copy(aq, ap); /* test va_copy */ + va_end(aq); + while (*fmt) switch(*fmt++) { case 's': /* string */ From lattner at cs.uiuc.edu Wed May 7 22:35:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 22:35:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Intrinsics.h Message-ID: <200305080334.WAA01674@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Intrinsics.h added (r1.1) --- Log message: Initial checkin for LLVM intrinsic functions --- Diffs of the changes: Index: llvm/include/llvm/Intrinsics.h diff -c /dev/null llvm/include/llvm/Intrinsics.h:1.1 *** /dev/null Wed May 7 22:34:05 2003 --- llvm/include/llvm/Intrinsics.h Wed May 7 22:33:54 2003 *************** *** 0 **** --- 1,21 ---- + //===-- llvm/Instrinsics.h - LLVM Intrinsic Function Handling ---*- C++ -*-===// + // + // This file defines a set of enums which allow processing of intrinsic + // functions. Values of these enum types are returned by + // Function::getIntrinsicID. + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_INTRINSICS_H + #define LLVM_INTRINSICS_H + + namespace LLVMIntrinsic { + enum ID { + not_intrinsic = 0, // Must be zero + va_start, // Used to represent a va_start call in C + va_end, // Used to represent a va_end call in C + va_copy, // Used to represent a va_copy call in C + }; + } + + #endif From lattner at cs.uiuc.edu Wed May 7 22:35:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 22:35:03 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Function.h Message-ID: <200305080334.WAA01685@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Function.h updated: 1.41 -> 1.42 --- Log message: Initial support for intrinsic functions --- Diffs of the changes: Index: llvm/include/llvm/Function.h diff -u llvm/include/llvm/Function.h:1.41 llvm/include/llvm/Function.h:1.42 --- llvm/include/llvm/Function.h:1.41 Wed Apr 16 15:28:30 2003 +++ llvm/include/llvm/Function.h Wed May 7 22:34:12 2003 @@ -87,6 +87,16 @@ /// virtual bool isExternal() const { return BasicBlocks.empty(); } + /// getIntrinsicID - This method returns the ID number of the specified + /// function, or LLVMIntrinsic::not_intrinsic if the function is not an + /// instrinsic, or if the pointer is null. This value is always defined to be + /// zero to allow easy checking for whether a function is intrinsic or not. + /// The particular intrinsic functions which correspond to this value are + /// defined in llvm/Intrinsics.h. + /// + unsigned getIntrinsicID() const; + bool isIntrinsic() const { return getIntrinsicID() != 0; } + // getNext/Prev - Return the next or previous function in the list. These // methods should never be used directly, and are only used to implement the // function list as part of the module. From lattner at cs.uiuc.edu Wed May 7 22:48:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 22:48:00 2003 Subject: [llvm-commits] CVS: llvm/test/Feature/varargs.ll Message-ID: <200305080347.WAA02453@apoc.cs.uiuc.edu> Changes in directory llvm/test/Feature: varargs.ll updated: 1.1 -> 1.2 --- Log message: Test the whole range of varargs handling stuff --- Diffs of the changes: Index: llvm/test/Feature/varargs.ll diff -u llvm/test/Feature/varargs.ll:1.1 llvm/test/Feature/varargs.ll:1.2 --- llvm/test/Feature/varargs.ll:1.1 Wed May 7 21:39:37 2003 +++ llvm/test/Feature/varargs.ll Wed May 7 22:46:51 2003 @@ -1,9 +1,21 @@ +; Demonstrate all of the variable argument handling intrinsic functions plus +; the va_arg instruction. - +implementation +declare void %llvm.va_start(sbyte**, ...) +declare void %llvm.va_copy(sbyte**, sbyte*) +declare void %llvm.va_end(sbyte**) int %test(int %X, ...) { %ap = alloca sbyte* - ; This is not a legal testcase, it just shows the syntax for va_arg + %aq = alloca sbyte* + call void (sbyte**, ...)* %llvm.va_start(sbyte** %ap, int %X) + %apv = load sbyte** %ap + call void %llvm.va_copy(sbyte** %aq, sbyte* %apv) + call void %llvm.va_end(sbyte** %aq) + %tmp = va_arg sbyte** %ap, int + + call void %llvm.va_end(sbyte** %ap) ret int %tmp } From lattner at cs.uiuc.edu Wed May 7 22:48:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 22:48:03 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Function.cpp Verifier.cpp Message-ID: <200305080347.WAA02475@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Function.cpp updated: 1.37 -> 1.38 Verifier.cpp updated: 1.47 -> 1.48 --- Log message: Add more support for intrinsic functions and for varargs stuff --- Diffs of the changes: Index: llvm/lib/VMCore/Function.cpp diff -u llvm/lib/VMCore/Function.cpp:1.37 llvm/lib/VMCore/Function.cpp:1.38 --- llvm/lib/VMCore/Function.cpp:1.37 Wed Apr 16 15:28:45 2003 +++ llvm/lib/VMCore/Function.cpp Wed May 7 22:47:33 2003 @@ -8,6 +8,7 @@ #include "llvm/Module.h" #include "llvm/DerivedTypes.h" #include "llvm/iOther.h" +#include "llvm/Intrinsics.h" #include "Support/LeakDetector.h" #include "SymbolTableListTraitsImpl.h" @@ -149,6 +150,41 @@ for (iterator I = begin(), E = end(); I != E; ++I) I->dropAllReferences(); } + +/// getIntrinsicID - This method returns the ID number of the specified +/// function, or LLVMIntrinsic::not_intrinsic if the function is not an +/// instrinsic, or if the pointer is null. This value is always defined to be +/// zero to allow easy checking for whether a function is intrinsic or not. The +/// particular intrinsic functions which correspond to this value are defined in +/// llvm/Intrinsics.h. +/// +unsigned Function::getIntrinsicID() const { + if (getName().size() <= 5 || getName()[4] != '.' || getName()[0] != 'l' || + getName()[1] != 'l' || getName()[2] != 'v' || getName()[3] != 'm') + return 0; // All intrinsics start with 'llvm.' + + switch (getName()[5]) { + case 'v': + if (getName().size() >= 9) { + switch (getName()[8]) { + case 's': + if (getName() == "llvm.va_start") return LLVMIntrinsic::va_start; + break; + case 'e': + if (getName() == "llvm.va_end") return LLVMIntrinsic::va_end; + break; + case 'c': + if (getName() == "llvm.va_copy") return LLVMIntrinsic::va_copy; + break; + } + } + break; + } + // The "llvm." namespace is reserved! + assert(0 && "Unknown LLVM intrinsic function!"); + return 0; +} + //===----------------------------------------------------------------------===// // GlobalVariable Implementation Index: llvm/lib/VMCore/Verifier.cpp diff -u llvm/lib/VMCore/Verifier.cpp:1.47 llvm/lib/VMCore/Verifier.cpp:1.48 --- llvm/lib/VMCore/Verifier.cpp:1.47 Wed May 7 21:44:12 2003 +++ llvm/lib/VMCore/Verifier.cpp Wed May 7 22:47:33 2003 @@ -43,6 +43,7 @@ #include "llvm/iMemory.h" #include "llvm/SymbolTable.h" #include "llvm/PassManager.h" +#include "llvm/Intrinsics.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Support/CFG.h" #include "llvm/Support/InstVisitor.h" @@ -140,6 +141,7 @@ void visitReturnInst(ReturnInst &RI); void visitUserOp1(Instruction &I); void visitUserOp2(Instruction &I) { visitUserOp1(I); } + void visitIntrinsicFunctionCall(LLVMIntrinsic::ID ID, CallInst &CI); // CheckFailed - A check failed, so print out the condition and the message // that failed. This provides a nice place to put a breakpoint if you want @@ -359,6 +361,10 @@ "Call parameter type does not match function signature!", CI.getOperand(i+1), FTy->getParamType(i)); + if (Function *F = CI.getCalledFunction()) + if (LLVMIntrinsic::ID ID = (LLVMIntrinsic::ID)F->getIntrinsicID()) + visitIntrinsicFunctionCall(ID, CI); + visitInstruction(CI); } @@ -495,6 +501,37 @@ "Instruction does not dominate all uses!", &I, Use); } } + + // Check to make sure that the "address of" an intrinsic function is never + // taken. + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + if (Function *F = dyn_cast(I.getOperand(i))) + Assert1(!F->isIntrinsic() || (i == 0 && isa(I)), + "Cannot take the address of an intrinsic!", &I); +} + +/// visitIntrinsicFunction - Allow intrinsics to be verified in different ways. +void Verifier::visitIntrinsicFunctionCall(LLVMIntrinsic::ID ID, CallInst &CI) { + Function *IF = CI.getCalledFunction(); + const FunctionType *FT = IF->getFunctionType(); + Assert1(IF->isExternal(), "Intrinsic functions should never be defined!", IF); + unsigned NumArgs; + + switch (ID) { + case LLVMIntrinsic::va_start: + Assert1(isa(CI.getOperand(2)), + "va_start second argument should be a function argument!", &CI); + NumArgs = 2; + break; + case LLVMIntrinsic::va_end: NumArgs = 1; break; + case LLVMIntrinsic::va_copy: NumArgs = 2; break; + case LLVMIntrinsic::not_intrinsic: + assert(0 && "Invalid intrinsic!"); NumArgs = 0; break; + } + + Assert1(FT->getNumParams() == NumArgs || (FT->getNumParams() < NumArgs && + FT->isVarArg()), + "Illegal # arguments for intrinsic function!", IF); } From lattner at cs.uiuc.edu Wed May 7 23:58:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 7 23:58:01 2003 Subject: [llvm-commits] CVS: llvm/www/docs/LangRef.html Message-ID: <200305080457.XAA01633@tank.cs.uiuc.edu> Changes in directory llvm/www/docs: LangRef.html updated: 1.20 -> 1.21 --- Log message: * Add information about LLVM intrinsics * Add information about the va_arg instruction * Add information about the llvm.va_* intrinsics --- Diffs of the changes: Index: llvm/www/docs/LangRef.html diff -u llvm/www/docs/LangRef.html:1.20 llvm/www/docs/LangRef.html:1.21 --- llvm/www/docs/LangRef.html:1.20 Fri Dec 13 00:01:21 2002 +++ llvm/www/docs/LangRef.html Wed May 7 23:57:36 2003 @@ -1,9 +1,9 @@ -llvm Assembly Language Reference Manual +LLVM Assembly Language Reference Manual - +
  llvm Assembly Language Reference Manual
  LLVM Language Reference Manual
    @@ -71,11 +71,18 @@
  1. 'phi' Instruction
  2. 'cast .. to' Instruction
  3. 'call' Instruction +
  4. 'va_arg' Instruction
- +
  • Intrinsic Functions +
      +
    1. Variable Argument Handling Intrinsics +
        +
      1. 'llvm.va_start' Intrinsic +
      2. 'llvm.va_end' Intrinsic +
      3. 'llvm.va_copy' Intrinsic +
      +

    Written by Chris Lattner and Vikram Adve

    @@ -130,7 +137,7 @@


    Well Formedness


    'va_arg' Instruction

    -Related Work +Intrinsic Functions
      - + +LLVM supports the notion of an "intrinsic function". These functions have well +known names and semantics, and are required to follow certain restrictions. +Overall, these instructions represent an extension mechanism for the LLVM +language that does not require changing all of the transformations in LLVM to +add to the language (or the bytecode reader/writer, the parser, etc...).

      + +Intrinsic function names must all start with an "llvm." prefix, this +prefix is reserved in LLVM for intrinsic names, thus functions may not be named +this. Intrinsic functions must always be external functions: you cannot define +the body of intrinsic functions. Intrinsic functions may only be used in call +or invoke instructions: it is illegal to take the address of an intrinsic +function. Additionally, because intrinsic functions are part of the LLVM +language, it is required that they all be documented here if any are added.

      + +Unless an intrinsic function is target-specific, there must be a lowering pass +to eliminate the intrinsic or all backends must support the intrinsic +function.

      -Codesigned virtual machines.

      -

      - -
      SafeTSA -
      Description here

      + +

    +
       +Variable Argument Handling Intrinsics +
      - -
      Java -
      Desciption here

      +Variable argument support is defined in LLVM with the va_arg instruction and these three intrinsic +functions. These function correspond almost directly to the similarly named +macros defined in the <stdarg.h> header file.

      + +All of these functions operate on arguments that use a target-specific type +"va_list". The LLVM assembly language reference manual does not define +what this type is, so all transformations should be prepared to handle +intrinsics with any type used.

      + +This example shows how the va_arg instruction +and the variable argument handling intrinsic functions are used.

      + +

      +int %test(int %X, ...) {
      +  ; Allocate two va_list items.  On this target, va_list is of type sbyte*
      +  %ap = alloca sbyte*
      +  %aq = alloca sbyte*
      +
      +  ; Initialize variable argument processing
      +  call void (sbyte**, ...)* %llvm.va_start(sbyte** %ap, int %X)
      +
      +  ; Read a single integer argument
      +  %tmp = va_arg sbyte** %ap, int 
      +
      +  ; Demonstrate usage of llvm.va_copy and llvm_va_end
      +  %apv = load sbyte** %ap
      +  call void %llvm.va_copy(sbyte** %aq, sbyte* %apv)
      +  call void %llvm.va_end(sbyte** %aq)
      +
      +  ; Stop processing of arguments.
      +  call void %llvm.va_end(sbyte** %ap)
      +  ret int %tmp
      +}
      +
      - -
      Microsoft .net -
      Desciption here

      + +


    'llvm.va_start' Intrinsic


    Vectorized Architectures


    'llvm.va_end' Intrinsic


    'llvm.va_copy' Intrinsic

      + +
      Syntax:
      +
      +  call void (va_list*, va_list)* %va_copy(<va_list>* <destarglist>,
      +                                          <va_list> <srcarglist>)
      +
      + +
      Overview:
      + +The 'llvm.va_copy' intrinsic copies the current argument position from +the source argument list to the destination argument list.

      + +

      Arguments:
      + +The first argument is a pointer to a va_list element to initialize. +The second argument is a va_list element to copy from.

      + + +

      Semantics:
      + +The 'llvm.va_copy' intrinsic works just like the va_copy macro +available in C. In a target-dependent way, it copies the source +va_list element into the destination list. This intrinsic is necessary +because the
      llvm.va_begin intrinsic may be +arbitrarily complex and require memory allocation, for example.

      @@ -1706,7 +1840,7 @@

      Chris Lattner
      -Last modified: Fri Dec 13 00:00:57 CST 2002 +Last modified: Wed May 7 23:56:16 CDT 2003 From lattner at cs.uiuc.edu Thu May 8 00:10:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 00:10:02 2003 Subject: [llvm-commits] CVS: llvm/www/docs/LangRef.html Message-ID: <200305080509.AAA01729@tank.cs.uiuc.edu> Changes in directory llvm/www/docs: LangRef.html updated: 1.21 -> 1.22 --- Log message: Update information about the switch instruction --- Diffs of the changes: Index: llvm/www/docs/LangRef.html diff -u llvm/www/docs/LangRef.html:1.21 llvm/www/docs/LangRef.html:1.22 --- llvm/www/docs/LangRef.html:1.21 Wed May 7 23:57:36 2003 +++ llvm/www/docs/LangRef.html Thu May 8 00:08:48 2003 @@ -684,76 +684,48 @@
      Syntax:
      -  ; Definitions for lookup indirect branch
      -  %switchtype = type [<anysize> x { uint, label }]
      +  switch int <value>, label <defaultdest> [ int <val>, label &dest>, ... ]
       
      -  ; Lookup indirect branch
      -  switch uint <value>, label <defaultdest>, %switchtype <switchtable>
      -
       
      Overview:
      -NOTE: The switch instruction may go away in the future. It is not very -well supported in LLVM anyway, so don't go to great lengths to support it. Talk -to Chris for more info if this concerns -you.

      - The 'switch' instruction is used to transfer control flow to one of several different places. It is a generalization of the 'br' instruction, allowing a branch to occur to one of many possible destinations.

      -The 'switch' statement supports two different styles of indirect -branching: lookup branching and indexed branching. Lookup branching is -generally useful if the values to switch on are spread far appart, where index -branching is useful if the values to switch on are generally dense.

      - -The two different forms of the 'switch' statement are simple hints to -the underlying implementation. For example, the compiler may choose to -implement a small indirect branch table as a series of predicated comparisons: -if it is faster for the target architecture.

      -

      Arguments:
      -The lookup form of the 'switch' instruction uses three parameters: a -'uint' comparison value 'value', a default 'label' -destination, and an array of pairs of comparison value constants and -'label's. The sized array must be a constant value.

      - -The indexed form of the 'switch' instruction uses three parameters: an -'uint' index value, a default 'label' and a sized array of -'label's. The 'dests' array must be a constant array. +The 'switch' instruction uses three parameters: a 'uint' +comparison value 'value', a default 'label' destination, and +an array of pairs of comparison value constants and 'label's.

      Semantics:
      -The lookup style switch statement specifies a table of values and destinations. +The switch instruction specifies a table of values and destinations. When the 'switch' instruction is executed, this table is searched for the given value. If the value is found, the corresponding destination is -branched to.

      +branched to, otherwise the default value it transfered to.

      -The index branch form simply looks up a label element directly in a table and -branches to it.

      +

      Implementation:
      -In either case, the compiler knows the static size of the array, because it is -provided as part of the constant values type.

      +Depending on properties of the target machine and the particular switch +instruction, this instruction may be code generated as a series of chained +conditional branches, or with a lookup table.

      Example:
         ; Emulate a conditional br instruction
         %Val = cast bool %value to uint
      -  switch uint %Val, label %truedest, [1 x label] [label %falsedest ]
      +  switch int %Val, label %truedest [int 0, label %falsedest ]
       
         ; Emulate an unconditional br instruction
      -  switch uint 0, label %dest, [ 0 x label] [ ]
      +  switch int 0, label %dest [ ]
       
         ; Implement a jump table:
      -  switch uint %val, label %otherwise, [3 x label] [ label %onzero, 
      -                                                    label %onone, 
      -                                                    label %ontwo ]
      -
      +  switch int %val, label %otherwise [ int 0, label %onzero, 
      +                                      int 1, label %onone, 
      +                                      int 2, label %ontwo ]
       
      @@ -1840,7 +1812,7 @@
      Chris Lattner
      -Last modified: Wed May 7 23:56:16 CDT 2003 +Last modified: Thu May 8 00:06:36 CDT 2003 From lattner at cs.uiuc.edu Thu May 8 10:56:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 10:56:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Verifier.cpp Message-ID: <200305081555.KAA16567@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Verifier.cpp updated: 1.48 -> 1.49 --- Log message: llvm.va_start only takes on argument now Verify that va_start doesn't occur in functions with no varargs --- Diffs of the changes: Index: llvm/lib/VMCore/Verifier.cpp diff -u llvm/lib/VMCore/Verifier.cpp:1.48 llvm/lib/VMCore/Verifier.cpp:1.49 --- llvm/lib/VMCore/Verifier.cpp:1.48 Wed May 7 22:47:33 2003 +++ llvm/lib/VMCore/Verifier.cpp Thu May 8 10:55:31 2003 @@ -131,7 +131,7 @@ void visitPHINode(PHINode &PN); void visitBinaryOperator(BinaryOperator &B); void visitShiftInst(ShiftInst &SI); - void visitVarArgInst(VarArgInst &VAI); + void visitVarArgInst(VarArgInst &VAI) { visitInstruction(VAI); } void visitCallInst(CallInst &CI); void visitGetElementPtrInst(GetElementPtrInst &GEP); void visitLoadInst(LoadInst &LI); @@ -409,13 +409,6 @@ visitInstruction(SI); } -void Verifier::visitVarArgInst(VarArgInst &VAI) { - Assert1(VAI.getParent()->getParent()->getFunctionType()->isVarArg(), - "va_arg instruction may only occur in function with variable args!", - &VAI); - visitInstruction(VAI); -} - void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { const Type *ElTy = GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(), @@ -519,9 +512,10 @@ switch (ID) { case LLVMIntrinsic::va_start: - Assert1(isa(CI.getOperand(2)), - "va_start second argument should be a function argument!", &CI); - NumArgs = 2; + Assert1(CI.getParent()->getParent()->getFunctionType()->isVarArg(), + "llvm.va_start intrinsic may only occur in function with variable" + " args!", &CI); + NumArgs = 1; break; case LLVMIntrinsic::va_end: NumArgs = 1; break; case LLVMIntrinsic::va_copy: NumArgs = 2; break; From lattner at cs.uiuc.edu Thu May 8 10:56:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 10:56:03 2003 Subject: [llvm-commits] CVS: llvm/www/docs/LangRef.html Message-ID: <200305081555.KAA16587@apoc.cs.uiuc.edu> Changes in directory llvm/www/docs: LangRef.html updated: 1.22 -> 1.23 --- Log message: va_start only takes on argument now. --- Diffs of the changes: Index: llvm/www/docs/LangRef.html diff -u llvm/www/docs/LangRef.html:1.22 llvm/www/docs/LangRef.html:1.23 --- llvm/www/docs/LangRef.html:1.22 Thu May 8 00:08:48 2003 +++ llvm/www/docs/LangRef.html Thu May 8 10:55:44 2003 @@ -1697,7 +1697,7 @@ %aq = alloca sbyte* ; Initialize variable argument processing - call void (sbyte**, ...)* %llvm.va_start(sbyte** %ap, int %X) + call void (sbyte**)* %llvm.va_start(sbyte** %ap) ; Read a single integer argument %tmp = va_arg sbyte** %ap, int @@ -1718,7 +1718,7 @@
      Syntax:
      -  call void (va_list*, ...)* %llvm.va_start(<va_list>* <arglist>, <argument>)
      +  call void (va_list*)* %llvm.va_start(<va_list>* <arglist>)
       
      Overview:
      @@ -1730,18 +1730,16 @@
      Arguments:
      -The first argument is a pointer to a va_list element to initialize. -The second argument is required to be the last LLVM argument before the -ellipsis. In the future, this restriction may be relaxed (to allow it to be -other arguments).

      +The argument is a pointer to a va_list element to initialize.

      Semantics:
      The 'llvm.va_start' intrinsic works just like the va_start macro available in C. In a target-dependent way, it initializes the -va_list element the first argument points to, so that the next call to -va_arg will produce the first variable argument passed to the -function.

      +va_list element the argument points to, so that the next call to +va_arg will produce the first variable argument passed to the function. +Unlike the C va_start macro, this intrinsic does not need to know the +last argument of the function, the compiler can figure that out.

      @@ -1812,7 +1810,7 @@

      Chris Lattner
      -Last modified: Thu May 8 00:06:36 CDT 2003 +Last modified: Thu May 8 10:48:46 CDT 2003 From lattner at cs.uiuc.edu Thu May 8 11:08:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 11:08:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/Interpreter/Execution.cpp Interpreter.h Message-ID: <200305081607.LAA16731@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/Interpreter: Execution.cpp updated: 1.84 -> 1.85 Interpreter.h updated: 1.25 -> 1.26 --- Log message: Add support for recording arguments passed through the ... of a varargs function --- Diffs of the changes: Index: llvm/tools/lli/Interpreter/Execution.cpp diff -u llvm/tools/lli/Interpreter/Execution.cpp:1.84 llvm/tools/lli/Interpreter/Execution.cpp:1.85 --- llvm/tools/lli/Interpreter/Execution.cpp:1.84 Thu Apr 24 23:21:19 2003 +++ llvm/tools/lli/Interpreter/Execution.cpp Thu May 8 11:06:52 2003 @@ -1038,14 +1038,14 @@ //===----------------------------------------------------------------------===// // callMethod - Execute the specified function... // -void Interpreter::callMethod(Function *M, +void Interpreter::callMethod(Function *F, const std::vector &ArgVals) { assert((ECStack.empty() || ECStack.back().Caller == 0 || ECStack.back().Caller->getNumOperands()-1 == ArgVals.size()) && "Incorrect number of arguments passed into function call!"); - if (M->isExternal()) { - GenericValue Result = callExternalMethod(M, ArgVals); - const Type *RetTy = M->getReturnType(); + if (F->isExternal()) { + GenericValue Result = callExternalMethod(F, ArgVals); + const Type *RetTy = F->getReturnType(); // Copy the result back into the result variable if we are not returning // void. @@ -1057,7 +1057,7 @@ SF.Caller = 0; // We returned from the call... } else if (!QuietMode) { // print it. - CW << "Function " << M->getType() << " \"" << M->getName() + CW << "Function " << F->getType() << " \"" << F->getName() << "\" returned "; print(RetTy, Result); std::cout << "\n"; @@ -1074,12 +1074,12 @@ // the function. Also calculate the number of values for each type slot // active. // - MethodInfo *MethInfo = (MethodInfo*)M->getOrCreateAnnotation(MethodInfoAID); + MethodInfo *MethInfo = (MethodInfo*)F->getOrCreateAnnotation(MethodInfoAID); ECStack.push_back(ExecutionContext()); // Make a new stack frame... ExecutionContext &StackFrame = ECStack.back(); // Fill it in... - StackFrame.CurMethod = M; - StackFrame.CurBB = M->begin(); + StackFrame.CurMethod = F; + StackFrame.CurBB = F->begin(); StackFrame.CurInst = StackFrame.CurBB->begin(); StackFrame.MethInfo = MethInfo; @@ -1097,11 +1097,17 @@ // Run through the function arguments and initialize their values... - assert(ArgVals.size() == M->asize() && + assert((ArgVals.size() == F->asize() || + (ArgVals.size() > F->asize() && F->getFunctionType()->isVarArg())) && "Invalid number of values passed to function invocation!"); + + // Handle non-varargs arguments... unsigned i = 0; - for (Function::aiterator AI = M->abegin(), E = M->aend(); AI != E; ++AI, ++i) + for (Function::aiterator AI = F->abegin(), E = F->aend(); AI != E; ++AI, ++i) SetValue(AI, ArgVals[i], StackFrame); + + // Handle varargs arguments... + StackFrame.VarArgs.assign(ArgVals.begin()+i, ArgVals.end()); } // executeInstruction - Interpret a single instruction, increment the "PC", and Index: llvm/tools/lli/Interpreter/Interpreter.h diff -u llvm/tools/lli/Interpreter/Interpreter.h:1.25 llvm/tools/lli/Interpreter/Interpreter.h:1.26 --- llvm/tools/lli/Interpreter/Interpreter.h:1.25 Mon Dec 23 17:59:41 2002 +++ llvm/tools/lli/Interpreter/Interpreter.h Thu May 8 11:06:52 2003 @@ -68,6 +68,7 @@ BasicBlock::iterator CurInst; // The next instruction to execute MethodInfo *MethInfo; // The MethInfo annotation for the function std::vector Values;// ValuePlanes for each type + std::vector VarArgs; // Values passed through an ellipsis BasicBlock *PrevBB; // The previous BB or null if in first BB CallInst *Caller; // Holds the call that called subframes. From lattner at cs.uiuc.edu Thu May 8 11:19:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 11:19:00 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/Interpreter/Execution.cpp ExecutionAnnotations.h ExternalFunctions.cpp Interpreter.cpp Interpreter.h Support.cpp UserInput.cpp Message-ID: <200305081618.LAA17028@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/Interpreter: Execution.cpp updated: 1.85 -> 1.86 ExecutionAnnotations.h updated: 1.9 -> 1.10 ExternalFunctions.cpp updated: 1.49 -> 1.50 Interpreter.cpp updated: 1.3 -> 1.4 Interpreter.h updated: 1.26 -> 1.27 Support.cpp updated: 1.6 -> 1.7 UserInput.cpp updated: 1.24 -> 1.25 --- Log message: A large number of simple changes: * s/Method/Function * Kill some obsolete (external) functions that used to be to support tracing --- Diffs of the changes: Index: llvm/tools/lli/Interpreter/Execution.cpp diff -u llvm/tools/lli/Interpreter/Execution.cpp:1.85 llvm/tools/lli/Interpreter/Execution.cpp:1.86 --- llvm/tools/lli/Interpreter/Execution.cpp:1.85 Thu May 8 11:06:52 2003 +++ llvm/tools/lli/Interpreter/Execution.cpp Thu May 8 11:18:31 2003 @@ -157,8 +157,8 @@ void Interpreter::initializeExecutionEngine() { TheEE = this; - AnnotationManager::registerAnnotationFactory(MethodInfoAID, - &MethodInfo::Create); + AnnotationManager::registerAnnotationFactory(FunctionInfoAID, + &FunctionInfo::Create); initializeSignalHandlers(); } @@ -588,7 +588,7 @@ } // Save previously executing meth - const Function *M = ECStack.back().CurMethod; + const Function *M = ECStack.back().CurFunction; // Pop the current stack frame... this invalidates SF ECStack.pop_back(); @@ -880,7 +880,7 @@ // and treat it as a function pointer. GenericValue SRC = getOperandValue(I.getCalledValue(), SF); - callMethod((Function*)GVTOP(SRC), ArgVals); + callFunction((Function*)GVTOP(SRC), ArgVals); } static void executePHINode(PHINode &I, ExecutionContext &SF) { @@ -1014,7 +1014,7 @@ // Dispatch and Execution Code //===----------------------------------------------------------------------===// -MethodInfo::MethodInfo(Function *F) : Annotation(MethodInfoAID) { +FunctionInfo::FunctionInfo(Function *F) : Annotation(FunctionInfoAID) { // Assign slot numbers to the function arguments... for (Function::const_aiterator AI = F->abegin(), E = F->aend(); AI != E; ++AI) AI->addAnnotation(new SlotNumber(getValueSlot(AI))); @@ -1027,7 +1027,7 @@ II->addAnnotation(new InstNumber(++InstNum, getValueSlot(II))); } -unsigned MethodInfo::getValueSlot(const Value *V) { +unsigned FunctionInfo::getValueSlot(const Value *V) { unsigned Plane = V->getType()->getUniqueID(); if (Plane >= NumPlaneElements.size()) NumPlaneElements.resize(Plane+1, 0); @@ -1036,15 +1036,15 @@ //===----------------------------------------------------------------------===// -// callMethod - Execute the specified function... +// callFunction - Execute the specified function... // -void Interpreter::callMethod(Function *F, - const std::vector &ArgVals) { +void Interpreter::callFunction(Function *F, + const std::vector &ArgVals) { assert((ECStack.empty() || ECStack.back().Caller == 0 || ECStack.back().Caller->getNumOperands()-1 == ArgVals.size()) && "Incorrect number of arguments passed into function call!"); if (F->isExternal()) { - GenericValue Result = callExternalMethod(F, ArgVals); + GenericValue Result = callExternalFunction(F, ArgVals); const Type *RetTy = F->getReturnType(); // Copy the result back into the result variable if we are not returning @@ -1074,23 +1074,24 @@ // the function. Also calculate the number of values for each type slot // active. // - MethodInfo *MethInfo = (MethodInfo*)F->getOrCreateAnnotation(MethodInfoAID); + FunctionInfo *FuncInfo = + (FunctionInfo*)F->getOrCreateAnnotation(FunctionInfoAID); ECStack.push_back(ExecutionContext()); // Make a new stack frame... ExecutionContext &StackFrame = ECStack.back(); // Fill it in... - StackFrame.CurMethod = F; + StackFrame.CurFunction = F; StackFrame.CurBB = F->begin(); StackFrame.CurInst = StackFrame.CurBB->begin(); - StackFrame.MethInfo = MethInfo; + StackFrame.FuncInfo = FuncInfo; // Initialize the values to nothing... - StackFrame.Values.resize(MethInfo->NumPlaneElements.size()); - for (unsigned i = 0; i < MethInfo->NumPlaneElements.size(); ++i) { - StackFrame.Values[i].resize(MethInfo->NumPlaneElements[i]); + StackFrame.Values.resize(FuncInfo->NumPlaneElements.size()); + for (unsigned i = 0; i < FuncInfo->NumPlaneElements.size(); ++i) { + StackFrame.Values[i].resize(FuncInfo->NumPlaneElements[i]); // Taint the initial values of stuff memset(&StackFrame.Values[i][0], 42, - MethInfo->NumPlaneElements[i]*sizeof(GenericValue)); + FuncInfo->NumPlaneElements[i]*sizeof(GenericValue)); } StackFrame.PrevBB = 0; // No previous BB for PHI nodes... @@ -1345,7 +1346,7 @@ // void Interpreter::printStackFrame(int FrameNo) { if (FrameNo == -1) FrameNo = CurFrame; - Function *F = ECStack[FrameNo].CurMethod; + Function *F = ECStack[FrameNo].CurFunction; const Type *RetTy = F->getReturnType(); CW << ((FrameNo == CurFrame) ? '>' : '-') << "#" << FrameNo << ". " Index: llvm/tools/lli/Interpreter/ExecutionAnnotations.h diff -u llvm/tools/lli/Interpreter/ExecutionAnnotations.h:1.9 llvm/tools/lli/Interpreter/ExecutionAnnotations.h:1.10 --- llvm/tools/lli/Interpreter/ExecutionAnnotations.h:1.9 Mon Dec 23 17:59:41 2002 +++ llvm/tools/lli/Interpreter/ExecutionAnnotations.h Thu May 8 11:18:31 2003 @@ -8,7 +8,7 @@ #define LLI_EXECUTION_ANNOTATIONS_H //===----------------------------------------------------------------------===// -// Support for MethodInfo annotations +// Support for FunctionInfo annotations //===----------------------------------------------------------------------===// // This annotation (attached only to Function objects) is used to cache useful @@ -18,20 +18,19 @@ // This annotation object is created on demand, and attaches other annotation // objects to the instructions in the function when it's created. // -static AnnotationID MethodInfoAID( +static AnnotationID FunctionInfoAID( AnnotationManager::getID("Interpreter::FunctionInfo")); -struct MethodInfo : public Annotation { - MethodInfo(Function *F); +struct FunctionInfo : public Annotation { + FunctionInfo(Function *F); std::vector NumPlaneElements; - - // Create - Factory function to allow MethodInfo annotations to be + // Create - Factory function to allow FunctionInfo annotations to be // created on demand. // static Annotation *Create(AnnotationID AID, const Annotable *O, void *) { - assert(AID == MethodInfoAID); - return new MethodInfo(cast((Value*)O)); // Simply invoke the ctor + assert(AID == FunctionInfoAID); + return new FunctionInfo(cast((Value*)O)); } private: @@ -47,7 +46,7 @@ // hold the the slot number for the value in its type plane. // // Entities have this annotation attached to them when the containing -// function has it's MethodInfo created (by the MethodInfo ctor). +// function has it's FunctionInfo created (by the FunctionInfo ctor). // static AnnotationID SlotNumberAID( AnnotationManager::getID("Interpreter::SlotNumber")); @@ -72,7 +71,7 @@ // calculating which value slot to store the result of the instruction in. // // Instructions have this annotation attached to them when the containing -// function has it's MethodInfo created (by the MethodInfo ctor). +// function has it's FunctionInfo created (by the FunctionInfo ctor). // struct InstNumber : public SlotNumber { unsigned InstNum; // Ranges from 1-> Index: llvm/tools/lli/Interpreter/ExternalFunctions.cpp diff -u llvm/tools/lli/Interpreter/ExternalFunctions.cpp:1.49 llvm/tools/lli/Interpreter/ExternalFunctions.cpp:1.50 --- llvm/tools/lli/Interpreter/ExternalFunctions.cpp:1.49 Fri Apr 25 13:28:44 2003 +++ llvm/tools/lli/Interpreter/ExternalFunctions.cpp Thu May 8 11:18:31 2003 @@ -22,7 +22,6 @@ #include #include using std::vector; -using std::cout; typedef GenericValue (*ExFunc)(FunctionType *, const vector &); static std::map Functions; @@ -78,7 +77,7 @@ ExtName += getTypeID(Ty); ExtName += "_" + M->getName(); - //cout << "Tried: '" << ExtName << "'\n"; + //std::cout << "Tried: '" << ExtName << "'\n"; ExFunc FnPtr = FuncNames[ExtName]; if (FnPtr == 0) FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str()); @@ -91,7 +90,7 @@ return FnPtr; } -GenericValue Interpreter::callExternalMethod(Function *M, +GenericValue Interpreter::callExternalFunction(Function *M, const vector &ArgVals) { TheInterpreter = this; @@ -100,8 +99,8 @@ std::map::iterator FI = Functions.find(M); ExFunc Fn = (FI == Functions.end()) ? lookupFunction(M) : FI->second; if (Fn == 0) { - cout << "Tried to execute an unknown external function: " - << M->getType()->getDescription() << " " << M->getName() << "\n"; + std::cout << "Tried to execute an unknown external function: " + << M->getType()->getDescription() << " " << M->getName() << "\n"; return GenericValue(); } @@ -117,85 +116,21 @@ // extern "C" { // Don't add C++ manglings to llvm mangling :) -// Implement void printstr([ubyte {x N}] *) -GenericValue lle_VP_printstr(FunctionType *M, - const vector &ArgVal){ - assert(ArgVal.size() == 1 && "printstr only takes one argument!"); - cout << (char*)GVTOP(ArgVal[0]); - return GenericValue(); -} - -// Implement 'void print(X)' for every type... -GenericValue lle_X_print(FunctionType *M, const vector &ArgVals) { - assert(ArgVals.size() == 1 && "generic print only takes one argument!"); - - Interpreter::print(M->getParamTypes()[0], ArgVals[0]); - return GenericValue(); -} - -// Implement 'void printVal(X)' for every type... -GenericValue lle_X_printVal(FunctionType *M, - const vector &ArgVal) { - assert(ArgVal.size() == 1 && "generic print only takes one argument!"); - - // Specialize print([ubyte {x N} ] *) and print(sbyte *) - if (const PointerType *PTy = - dyn_cast(M->getParamTypes()[0].get())) - if (PTy->getElementType() == Type::SByteTy || - isa(PTy->getElementType())) { - return lle_VP_printstr(M, ArgVal); - } - - Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]); - return GenericValue(); -} - -// Implement 'void printString(X)' -// Argument must be [ubyte {x N} ] * or sbyte * -GenericValue lle_X_printString(FunctionType *M, - const vector &ArgVal) { - assert(ArgVal.size() == 1 && "generic print only takes one argument!"); - return lle_VP_printstr(M, ArgVal); -} - -// Implement 'void print(X)' for each primitive type or pointer type -#define PRINT_TYPE_FUNC(TYPENAME,TYPEID) \ - GenericValue lle_X_print##TYPENAME(FunctionType *M,\ - const vector &ArgVal) {\ - assert(ArgVal.size() == 1 && "generic print only takes one argument!");\ - assert(M->getParamTypes()[0].get()->getPrimitiveID() == Type::TYPEID);\ - Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\ - return GenericValue();\ - } - -PRINT_TYPE_FUNC(SByte, SByteTyID) -PRINT_TYPE_FUNC(UByte, UByteTyID) -PRINT_TYPE_FUNC(Short, ShortTyID) -PRINT_TYPE_FUNC(UShort, UShortTyID) -PRINT_TYPE_FUNC(Int, IntTyID) -PRINT_TYPE_FUNC(UInt, UIntTyID) -PRINT_TYPE_FUNC(Long, LongTyID) -PRINT_TYPE_FUNC(ULong, ULongTyID) -PRINT_TYPE_FUNC(Float, FloatTyID) -PRINT_TYPE_FUNC(Double, DoubleTyID) -PRINT_TYPE_FUNC(Pointer, PointerTyID) - - // void putchar(sbyte) GenericValue lle_Vb_putchar(FunctionType *M, const vector &Args) { - cout << Args[0].SByteVal; + std::cout << Args[0].SByteVal; return GenericValue(); } // int putchar(int) GenericValue lle_ii_putchar(FunctionType *M, const vector &Args) { - cout << ((char)Args[0].IntVal) << std::flush; + std::cout << ((char)Args[0].IntVal) << std::flush; return Args[0]; } // void putchar(ubyte) GenericValue lle_VB_putchar(FunctionType *M, const vector &Args) { - cout << Args[0].SByteVal << std::flush; + std::cout << Args[0].SByteVal << std::flush; return Args[0]; } @@ -395,7 +330,7 @@ sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break; case 's': sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break; - default: cout << ""; + default: std::cout << ""; ArgNo++; break; } strcpy(OutputBuffer, Buffer); @@ -413,7 +348,7 @@ NewArgs.push_back(PTOGV(Buffer)); NewArgs.insert(NewArgs.end(), Args.begin(), Args.end()); GenericValue GV = lle_X_sprintf(M, NewArgs); - cout << Buffer; + std::cout << Buffer; return GV; } @@ -763,22 +698,7 @@ } // End extern "C" -void Interpreter::initializeExternalMethods() { - FuncNames["lle_VP_printstr"] = lle_VP_printstr; - FuncNames["lle_X_print"] = lle_X_print; - FuncNames["lle_X_printVal"] = lle_X_printVal; - FuncNames["lle_X_printString"] = lle_X_printString; - FuncNames["lle_X_printUByte"] = lle_X_printUByte; - FuncNames["lle_X_printSByte"] = lle_X_printSByte; - FuncNames["lle_X_printUShort"] = lle_X_printUShort; - FuncNames["lle_X_printShort"] = lle_X_printShort; - FuncNames["lle_X_printInt"] = lle_X_printInt; - FuncNames["lle_X_printUInt"] = lle_X_printUInt; - FuncNames["lle_X_printLong"] = lle_X_printLong; - FuncNames["lle_X_printULong"] = lle_X_printULong; - FuncNames["lle_X_printFloat"] = lle_X_printFloat; - FuncNames["lle_X_printDouble"] = lle_X_printDouble; - FuncNames["lle_X_printPointer"] = lle_X_printPointer; +void Interpreter::initializeExternalFunctions() { FuncNames["lle_Vb_putchar"] = lle_Vb_putchar; FuncNames["lle_ii_putchar"] = lle_ii_putchar; FuncNames["lle_VB_putchar"] = lle_VB_putchar; @@ -810,7 +730,7 @@ FuncNames["lle_X_strcat"] = lle_X_strcat; FuncNames["lle_X_strcpy"] = lle_X_strcpy; FuncNames["lle_X_strlen"] = lle_X_strlen; - FuncNames["lle_X___strdup"] = lle_X___strdup; + FuncNames["lle_X___strdup"] = lle_X___strdup; FuncNames["lle_X_memset"] = lle_X_memset; FuncNames["lle_X_memcpy"] = lle_X_memcpy; Index: llvm/tools/lli/Interpreter/Interpreter.cpp diff -u llvm/tools/lli/Interpreter/Interpreter.cpp:1.3 llvm/tools/lli/Interpreter/Interpreter.cpp:1.4 --- llvm/tools/lli/Interpreter/Interpreter.cpp:1.3 Sat Apr 26 15:11:09 2003 +++ llvm/tools/lli/Interpreter/Interpreter.cpp Thu May 8 11:18:31 2003 @@ -32,7 +32,7 @@ setTargetData(TD); // Initialize the "backend" initializeExecutionEngine(); - initializeExternalMethods(); + initializeExternalFunctions(); CW.setModule(M); // Update Writer } @@ -42,7 +42,7 @@ const std::vector &Args) { // Start interpreter into the main function... // - if (!callMainMethod(MainFunction, Args) && !Debug) { + if (!callMainFunction(MainFunction, Args) && !Debug) { // If not in debug mode and if the call succeeded, run the code now... run(); } Index: llvm/tools/lli/Interpreter/Interpreter.h diff -u llvm/tools/lli/Interpreter/Interpreter.h:1.26 llvm/tools/lli/Interpreter/Interpreter.h:1.27 --- llvm/tools/lli/Interpreter/Interpreter.h:1.26 Thu May 8 11:06:52 2003 +++ llvm/tools/lli/Interpreter/Interpreter.h Thu May 8 11:18:31 2003 @@ -19,7 +19,7 @@ extern CachedWriter CW; // Object to accelerate printing of LLVM -struct MethodInfo; // Defined in ExecutionAnnotations.h +struct FunctionInfo; // Defined in ExecutionAnnotations.h class CallInst; class ReturnInst; class BranchInst; @@ -63,10 +63,10 @@ // executing. // struct ExecutionContext { - Function *CurMethod; // The currently executing function + Function *CurFunction;// The currently executing function BasicBlock *CurBB; // The currently executing BB BasicBlock::iterator CurInst; // The next instruction to execute - MethodInfo *MethInfo; // The MethInfo annotation for the function + FunctionInfo *FuncInfo; // The FuncInfo annotation for the function std::vector Values;// ValuePlanes for each type std::vector VarArgs; // Values passed through an ellipsis @@ -111,21 +111,21 @@ void handleUserInput(); // User Interation Methods... - bool callMethod(const std::string &Name); // return true on failure + bool callFunction(const std::string &Name); // return true on failure void setBreakpoint(const std::string &Name); void infoValue(const std::string &Name); void print(const std::string &Name); static void print(const Type *Ty, GenericValue V); static void printValue(const Type *Ty, GenericValue V); - bool callMainMethod(const std::string &MainName, - const std::vector &InputFilename); + bool callMainFunction(const std::string &MainName, + const std::vector &InputFilename); void list(); // Do the 'list' command void printStackTrace(); // Do the 'backtrace' command // Code execution methods... - void callMethod(Function *F, const std::vector &ArgVals); + void callFunction(Function *F, const std::vector &ArgVals); bool executeInstruction(); // Execute one instruction... void stepInstruction(); // Do the 'step' command @@ -138,13 +138,13 @@ void executeRetInst(ReturnInst &I, ExecutionContext &SF); void executeBrInst(BranchInst &I, ExecutionContext &SF); void executeAllocInst(AllocationInst &I, ExecutionContext &SF); - GenericValue callExternalMethod(Function *F, - const std::vector &ArgVals); + GenericValue callExternalFunction(Function *F, + const std::vector &ArgVals); void exitCalled(GenericValue GV); - // getCurrentMethod - Return the currently executing method - inline Function *getCurrentMethod() const { - return CurFrame < 0 ? 0 : ECStack[CurFrame].CurMethod; + // getCurrentFunction - Return the currently executing function + inline Function *getCurrentFunction() const { + return CurFrame < 0 ? 0 : ECStack[CurFrame].CurFunction; } // isStopped - Return true if a program is stopped. Return false if no @@ -194,7 +194,7 @@ void initializeExecutionEngine(); - void initializeExternalMethods(); + void initializeExternalFunctions(); }; #endif Index: llvm/tools/lli/Interpreter/Support.cpp diff -u llvm/tools/lli/Interpreter/Support.cpp:1.6 llvm/tools/lli/Interpreter/Support.cpp:1.7 --- llvm/tools/lli/Interpreter/Support.cpp:1.6 Mon Dec 23 17:59:41 2002 +++ llvm/tools/lli/Interpreter/Support.cpp Thu May 8 11:18:31 2003 @@ -8,8 +8,6 @@ #include "llvm/SymbolTable.h" #include "llvm/Assembly/Writer.h" #include "llvm/Module.h" -#include -using std::cout; //===----------------------------------------------------------------------===// // @@ -36,9 +34,9 @@ // std::vector Interpreter::LookupMatchingNames(const std::string &Name) { std::vector Results; - Function *CurMeth = getCurrentMethod(); + Function *CurFunc = getCurrentFunction(); - if (CurMeth) ::LookupMatchingNames(Name, CurMeth->getSymbolTable(), Results); + if (CurFunc) ::LookupMatchingNames(Name, CurFunc->getSymbolTable(), Results); ::LookupMatchingNames(Name, getModule().getSymbolTable(), Results); return Results; } @@ -52,25 +50,26 @@ switch (Opts.size()) { case 1: return Opts[0]; case 0: - cout << "Error: no entities named '" << Name << "' found!\n"; + std::cout << "Error: no entities named '" << Name << "' found!\n"; return 0; default: break; // Must prompt user... } - cout << "Multiple entities named '" << Name << "' found! Please choose:\n"; - cout << " 0. Cancel operation\n"; + std::cout << "Multiple entities named '" << Name + << "' found! Please choose:\n"; + std::cout << " 0. Cancel operation\n"; for (unsigned i = 0; i < Opts.size(); ++i) { - cout << " " << (i+1) << "."; - WriteAsOperand(cout, Opts[i]) << "\n"; + std::cout << " " << (i+1) << "."; + WriteAsOperand(std::cout, Opts[i]) << "\n"; } unsigned Option; do { - cout << "lli> " << std::flush; + std::cout << "lli> " << std::flush; std::cin >> Option; if (Option > Opts.size()) - cout << "Invalid selection: Please choose from 0 to " << Opts.size() - << "\n"; + std::cout << "Invalid selection: Please choose from 0 to " << Opts.size() + << "\n"; } while (Option > Opts.size()); if (Option == 0) return 0; Index: llvm/tools/lli/Interpreter/UserInput.cpp diff -u llvm/tools/lli/Interpreter/UserInput.cpp:1.24 llvm/tools/lli/Interpreter/UserInput.cpp:1.25 --- llvm/tools/lli/Interpreter/UserInput.cpp:1.24 Mon Dec 23 17:59:41 2002 +++ llvm/tools/lli/Interpreter/UserInput.cpp Thu May 8 11:18:31 2003 @@ -10,9 +10,6 @@ #include "llvm/Function.h" #include "llvm/Transforms/Utils/Linker.h" #include -using std::string; -using std::cout; -using std::cin; enum CommandID { Quit, Help, // Basics @@ -29,10 +26,10 @@ enum CommandID CID; inline bool operator<(const CommandTableElement &E) const { - return string(Name) < string(E.Name); + return std::string(Name) < std::string(E.Name); } - inline bool operator==(const string &S) const { - return string(Name) == S; + inline bool operator==(const std::string &S) const { + return std::string(Name) == S; } } CommandTable[] = { { "quit" , Quit }, { "q", Quit }, { "", Quit }, // Empty str = eof @@ -76,25 +73,25 @@ printCurrentInstruction(); do { - string Command; - cout << "lli> " << std::flush; - cin >> Command; + std::string Command; + std::cout << "lli> " << std::flush; + std::cin >> Command; CommandTableElement *E = find(CommandTable, CommandTableEnd, Command); if (E == CommandTableEnd) { - cout << "Error: '" << Command << "' not recognized!\n"; + std::cout << "Error: '" << Command << "' not recognized!\n"; continue; } switch (E->CID) { case Quit: UserQuit = true; break; case Print: - cin >> Command; + std::cin >> Command; print(Command); break; case Info: - cin >> Command; + std::cin >> Command; infoValue(Command); break; @@ -102,32 +99,32 @@ case StackTrace: printStackTrace(); break; case Up: if (CurFrame > 0) { --CurFrame; printStackFrame(); } - else cout << "Error: Already at root of stack!\n"; + else std::cout << "Error: Already at root of stack!\n"; break; case Down: if ((unsigned)CurFrame < ECStack.size()-1) { ++CurFrame; printStackFrame(); } else - cout << "Error: Already at bottom of stack!\n"; + std::cout << "Error: Already at bottom of stack!\n"; break; case Next: nextInstruction(); break; case Step: stepInstruction(); break; case Run: run(); break; case Finish: finish(); break; case Call: - cin >> Command; - callMethod(Command); // Enter the specified function + std::cin >> Command; + callFunction(Command); // Enter the specified function finish(); // Run until it's complete break; case TraceOpt: Trace = !Trace; - cout << "Tracing " << (Trace ? "enabled\n" : "disabled\n"); + std::cout << "Tracing " << (Trace ? "enabled\n" : "disabled\n"); break; default: - cout << "Command '" << Command << "' unimplemented!\n"; + std::cout << "Command '" << Command << "' unimplemented!\n"; break; } @@ -137,15 +134,15 @@ //===----------------------------------------------------------------------===// // setBreakpoint - Enable a breakpoint at the specified location // -void Interpreter::setBreakpoint(const string &Name) { +void Interpreter::setBreakpoint(const std::string &Name) { Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name)); // TODO: Set a breakpoint on PickedVal } //===----------------------------------------------------------------------===// -// callMethod - Enter the specified method... +// callFunction - Enter the specified function... // -bool Interpreter::callMethod(const string &Name) { +bool Interpreter::callFunction(const std::string &Name) { std::vector Options = LookupMatchingNames(Name); for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches... @@ -164,7 +161,7 @@ std::vector Args; // TODO, get args from user... - callMethod(F, Args); // Start executing it... + callFunction(F, Args); // Start executing it... // Reset the current frame location to the top of stack CurFrame = ECStack.size()-1; @@ -172,11 +169,11 @@ return false; } -// callMainMethod - This is a nasty gross hack that will dissapear when -// callMethod can parse command line options and stuff for us. +// callMainFunction - This is a nasty gross hack that will dissapear when +// callFunction can parse command line options and stuff for us. // -bool Interpreter::callMainMethod(const string &Name, - const std::vector &InputArgv) { +bool Interpreter::callMainFunction(const std::string &Name, + const std::vector &InputArgv) { std::vector Options = LookupMatchingNames(Name); for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches... @@ -196,7 +193,8 @@ std::vector Args; switch (MT->getParamTypes().size()) { default: - cout << "Unknown number of arguments to synthesize for '" << Name << "'!\n"; + std::cout << "Unknown number of arguments to synthesize for '" << Name + << "'!\n"; return true; case 2: { PointerType *SPP = PointerType::get(PointerType::get(Type::SByteTy)); @@ -211,7 +209,7 @@ // fallthrough case 1: if (!MT->getParamTypes()[0]->isInteger()) { - cout << "First argument of '" << Name << "' should be an integer!\n"; + std::cout << "First argument of '" << Name << "' should be an integer!\n"; return true; } else { GenericValue GV; GV.UIntVal = InputArgv.size(); @@ -222,7 +220,7 @@ break; } - callMethod(M, Args); // Start executing it... + callFunction(M, Args); // Start executing it... // Reset the current frame location to the top of stack CurFrame = ECStack.size()-1; @@ -234,13 +232,13 @@ void Interpreter::list() { if (ECStack.empty()) - cout << "Error: No program executing!\n"; + std::cout << "Error: No program executing!\n"; else - CW << ECStack[CurFrame].CurMethod; // Just print the function out... + CW << ECStack[CurFrame].CurFunction; // Just print the function out... } void Interpreter::printStackTrace() { - if (ECStack.empty()) cout << "No program executing!\n"; + if (ECStack.empty()) std::cout << "No program executing!\n"; for (unsigned i = 0; i < ECStack.size(); ++i) { printStackFrame((int)i); From lattner at cs.uiuc.edu Thu May 8 11:53:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 11:53:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/ExecutionEngine.cpp ExecutionEngine.h Message-ID: <200305081652.LAA17578@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli: ExecutionEngine.cpp updated: 1.8 -> 1.9 ExecutionEngine.h updated: 1.1 -> 1.2 --- Log message: Add a pointersize/endianness safe load routine to match the store routine --- Diffs of the changes: Index: llvm/tools/lli/ExecutionEngine.cpp diff -u llvm/tools/lli/ExecutionEngine.cpp:1.8 llvm/tools/lli/ExecutionEngine.cpp:1.9 --- llvm/tools/lli/ExecutionEngine.cpp:1.8 Wed May 7 15:31:37 2003 +++ llvm/tools/lli/ExecutionEngine.cpp Thu May 8 11:52:16 2003 @@ -152,6 +152,82 @@ } } +GenericValue ExecutionEngine::LoadValueFromMemory(GenericValue *Ptr, + const Type *Ty) { + GenericValue Result; + if (getTargetData().isLittleEndian()) { + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + case Type::UByteTyID: + case Type::SByteTyID: Result.UByteVal = Ptr->Untyped[0]; break; + case Type::UShortTyID: + case Type::ShortTyID: Result.UShortVal = (unsigned)Ptr->Untyped[0] | + ((unsigned)Ptr->Untyped[1] << 8); + break; + Load4BytesLittleEndian: + case Type::FloatTyID: + case Type::UIntTyID: + case Type::IntTyID: Result.UIntVal = (unsigned)Ptr->Untyped[0] | + ((unsigned)Ptr->Untyped[1] << 8) | + ((unsigned)Ptr->Untyped[2] << 16) | + ((unsigned)Ptr->Untyped[3] << 24); + break; + case Type::PointerTyID: if (getModule().has32BitPointers()) + goto Load4BytesLittleEndian; + case Type::DoubleTyID: + case Type::ULongTyID: + case Type::LongTyID: Result.ULongVal = (uint64_t)Ptr->Untyped[0] | + ((uint64_t)Ptr->Untyped[1] << 8) | + ((uint64_t)Ptr->Untyped[2] << 16) | + ((uint64_t)Ptr->Untyped[3] << 24) | + ((uint64_t)Ptr->Untyped[4] << 32) | + ((uint64_t)Ptr->Untyped[5] << 40) | + ((uint64_t)Ptr->Untyped[6] << 48) | + ((uint64_t)Ptr->Untyped[7] << 56); + break; + default: + std::cout << "Cannot load value of type " << *Ty << "!\n"; + abort(); + } + } else { + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + case Type::UByteTyID: + case Type::SByteTyID: Result.UByteVal = Ptr->Untyped[0]; break; + case Type::UShortTyID: + case Type::ShortTyID: Result.UShortVal = (unsigned)Ptr->Untyped[1] | + ((unsigned)Ptr->Untyped[0] << 8); + break; + Load4BytesBigEndian: + case Type::FloatTyID: + case Type::UIntTyID: + case Type::IntTyID: Result.UIntVal = (unsigned)Ptr->Untyped[3] | + ((unsigned)Ptr->Untyped[2] << 8) | + ((unsigned)Ptr->Untyped[1] << 16) | + ((unsigned)Ptr->Untyped[0] << 24); + break; + case Type::PointerTyID: if (getModule().has32BitPointers()) + goto Load4BytesBigEndian; + case Type::DoubleTyID: + case Type::ULongTyID: + case Type::LongTyID: Result.ULongVal = (uint64_t)Ptr->Untyped[7] | + ((uint64_t)Ptr->Untyped[6] << 8) | + ((uint64_t)Ptr->Untyped[5] << 16) | + ((uint64_t)Ptr->Untyped[4] << 24) | + ((uint64_t)Ptr->Untyped[3] << 32) | + ((uint64_t)Ptr->Untyped[2] << 40) | + ((uint64_t)Ptr->Untyped[1] << 48) | + ((uint64_t)Ptr->Untyped[0] << 56); + break; + default: + std::cout << "Cannot load value of type " << *Ty << "!\n"; + abort(); + } + } + return Result; +} + + // InitializeMemory - Recursive function to apply a Constant value into the // specified memory location... // Index: llvm/tools/lli/ExecutionEngine.h diff -u llvm/tools/lli/ExecutionEngine.h:1.1 llvm/tools/lli/ExecutionEngine.h:1.2 --- llvm/tools/lli/ExecutionEngine.h:1.1 Mon Dec 23 18:01:01 2002 +++ llvm/tools/lli/ExecutionEngine.h Thu May 8 11:52:16 2003 @@ -79,6 +79,7 @@ public: // FIXME: protected: // API shared among subclasses GenericValue getConstantValue(const Constant *C); void StoreValueToMemory(GenericValue Val, GenericValue *Ptr, const Type *Ty); + GenericValue LoadValueFromMemory(GenericValue *Ptr, const Type *Ty); void *CreateArgv(const std::vector &InputArgv); void InitializeMemory(const Constant *Init, void *Addr); }; From lattner at cs.uiuc.edu Thu May 8 11:53:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 11:53:04 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/Interpreter/Execution.cpp ExternalFunctions.cpp Message-ID: <200305081652.LAA17592@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/Interpreter: Execution.cpp updated: 1.86 -> 1.87 ExternalFunctions.cpp updated: 1.50 -> 1.51 --- Log message: Implement varargs support for LLI! --- Diffs of the changes: Index: llvm/tools/lli/Interpreter/Execution.cpp diff -u llvm/tools/lli/Interpreter/Execution.cpp:1.86 llvm/tools/lli/Interpreter/Execution.cpp:1.87 --- llvm/tools/lli/Interpreter/Execution.cpp:1.86 Thu May 8 11:18:31 2003 +++ llvm/tools/lli/Interpreter/Execution.cpp Thu May 8 11:52:43 2003 @@ -761,78 +761,7 @@ void Interpreter::executeLoadInst(LoadInst &I, ExecutionContext &SF) { GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); GenericValue *Ptr = (GenericValue*)GVTOP(SRC); - GenericValue Result; - - if (TD.isLittleEndian()) { - switch (I.getType()->getPrimitiveID()) { - case Type::BoolTyID: - case Type::UByteTyID: - case Type::SByteTyID: Result.UByteVal = Ptr->Untyped[0]; break; - case Type::UShortTyID: - case Type::ShortTyID: Result.UShortVal = (unsigned)Ptr->Untyped[0] | - ((unsigned)Ptr->Untyped[1] << 8); - break; - Load4BytesLittleEndian: - case Type::FloatTyID: - case Type::UIntTyID: - case Type::IntTyID: Result.UIntVal = (unsigned)Ptr->Untyped[0] | - ((unsigned)Ptr->Untyped[1] << 8) | - ((unsigned)Ptr->Untyped[2] << 16) | - ((unsigned)Ptr->Untyped[3] << 24); - break; - case Type::PointerTyID: if (getModule().has32BitPointers()) - goto Load4BytesLittleEndian; - case Type::DoubleTyID: - case Type::ULongTyID: - case Type::LongTyID: Result.ULongVal = (uint64_t)Ptr->Untyped[0] | - ((uint64_t)Ptr->Untyped[1] << 8) | - ((uint64_t)Ptr->Untyped[2] << 16) | - ((uint64_t)Ptr->Untyped[3] << 24) | - ((uint64_t)Ptr->Untyped[4] << 32) | - ((uint64_t)Ptr->Untyped[5] << 40) | - ((uint64_t)Ptr->Untyped[6] << 48) | - ((uint64_t)Ptr->Untyped[7] << 56); - break; - default: - std::cout << "Cannot load value of type " << *I.getType() << "!\n"; - abort(); - } - } else { - switch (I.getType()->getPrimitiveID()) { - case Type::BoolTyID: - case Type::UByteTyID: - case Type::SByteTyID: Result.UByteVal = Ptr->Untyped[0]; break; - case Type::UShortTyID: - case Type::ShortTyID: Result.UShortVal = (unsigned)Ptr->Untyped[1] | - ((unsigned)Ptr->Untyped[0] << 8); - break; - Load4BytesBigEndian: - case Type::FloatTyID: - case Type::UIntTyID: - case Type::IntTyID: Result.UIntVal = (unsigned)Ptr->Untyped[3] | - ((unsigned)Ptr->Untyped[2] << 8) | - ((unsigned)Ptr->Untyped[1] << 16) | - ((unsigned)Ptr->Untyped[0] << 24); - break; - case Type::PointerTyID: if (getModule().has32BitPointers()) - goto Load4BytesBigEndian; - case Type::DoubleTyID: - case Type::ULongTyID: - case Type::LongTyID: Result.ULongVal = (uint64_t)Ptr->Untyped[7] | - ((uint64_t)Ptr->Untyped[6] << 8) | - ((uint64_t)Ptr->Untyped[5] << 16) | - ((uint64_t)Ptr->Untyped[4] << 24) | - ((uint64_t)Ptr->Untyped[3] << 32) | - ((uint64_t)Ptr->Untyped[2] << 40) | - ((uint64_t)Ptr->Untyped[1] << 48) | - ((uint64_t)Ptr->Untyped[0] << 56); - break; - default: - std::cout << "Cannot load value of type " << *I.getType() << "!\n"; - abort(); - } - } - + GenericValue Result = LoadValueFromMemory(Ptr, I.getType()); SetValue(&I, Result, SF); } @@ -1009,6 +938,26 @@ SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF); } +static void executeVarArgInst(VarArgInst &I, ExecutionContext &SF) { + // Get the pointer to the valist element. LLI treats the valist in memory as + // an integer. + GenericValue VAListPtr = getOperandValue(I.getOperand(0), SF); + + // Load the pointer + GenericValue VAList = + TheEE->LoadValueFromMemory((GenericValue *)GVTOP(VAListPtr), Type::UIntTy); + + unsigned Argument = VAList.IntVal++; + + // Update the valist to point to the next argument... + TheEE->StoreValueToMemory(VAList, (GenericValue *)GVTOP(VAListPtr), + Type::UIntTy); + + // Set the value... + assert(Argument < SF.VarArgs.size() && + "Accessing past the last vararg argument!"); + SetValue(&I, SF.VarArgs[Argument], SF); +} //===----------------------------------------------------------------------===// // Dispatch and Execution Code @@ -1166,9 +1115,10 @@ // Miscellaneous Instructions case Instruction::Call: executeCallInst (cast (I), SF); break; case Instruction::PHINode: executePHINode (cast (I), SF); break; + case Instruction::Cast: executeCastInst (cast (I), SF); break; case Instruction::Shl: executeShlInst (cast(I), SF); break; case Instruction::Shr: executeShrInst (cast(I), SF); break; - case Instruction::Cast: executeCastInst (cast (I), SF); break; + case Instruction::VarArg: executeVarArgInst(cast(I),SF); break; default: std::cout << "Don't know how to execute this instruction!\n-->" << I; abort(); Index: llvm/tools/lli/Interpreter/ExternalFunctions.cpp diff -u llvm/tools/lli/Interpreter/ExternalFunctions.cpp:1.50 llvm/tools/lli/Interpreter/ExternalFunctions.cpp:1.51 --- llvm/tools/lli/Interpreter/ExternalFunctions.cpp:1.50 Thu May 8 11:18:31 2003 +++ llvm/tools/lli/Interpreter/ExternalFunctions.cpp Thu May 8 11:52:43 2003 @@ -695,6 +695,35 @@ return GV; } +//===----------------------------------------------------------------------===// +// LLVM Intrinsic Functions... +//===----------------------------------------------------------------------===// + +// void llvm.va_start( *) - Implement the va_start operation... +GenericValue llvm_va_start(FunctionType *F, const vector &Args) { + assert(Args.size() == 1); + GenericValue *VAListP = (GenericValue *)GVTOP(Args[0]); + GenericValue Val; + Val.UIntVal = 0; // Start at the first '...' argument... + TheInterpreter->StoreValueToMemory(Val, VAListP, Type::UIntTy); + return GenericValue(); +} + +// void llvm.va_end( *) - Implement the va_end operation... +GenericValue llvm_va_end(FunctionType *F, const vector &Args) { + assert(Args.size() == 1); + return GenericValue(); // Noop! +} + +// void llvm.va_copy( *, ) - Implement the va_copy +// operation... +GenericValue llvm_va_copy(FunctionType *F, const vector &Args) { + assert(Args.size() == 2); + GenericValue *DestVAList = (GenericValue*)GVTOP(Args[0]); + TheInterpreter->StoreValueToMemory(Args[1], DestVAList, Type::UIntTy); + return GenericValue(); +} + } // End extern "C" @@ -748,4 +777,8 @@ FuncNames["lle_X_ungetc"] = lle_X_ungetc; FuncNames["lle_X_fprintf"] = lle_X_fprintf; FuncNames["lle_X_freopen"] = lle_X_freopen; + + FuncNames["lle_X_llvm.va_start"]= llvm_va_start; + FuncNames["lle_X_llvm.va_end"] = llvm_va_end; + FuncNames["lle_X_llvm.va_copy"] = llvm_va_copy; } From jstanley at cs.uiuc.edu Thu May 8 12:18:02 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu May 8 12:18:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/InstManip.h PhaseInfo.h Phases.cpp SparcInstManip.cpp SparcInstManip.h Message-ID: <200305081627.LAA20267@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib: InstManip.h updated: 1.15 -> 1.16 PhaseInfo.h updated: 1.2 -> 1.3 Phases.cpp updated: 1.24 -> 1.25 SparcInstManip.cpp updated: 1.4 -> 1.5 SparcInstManip.h updated: 1.5 -> 1.6 --- Log message: Phase 5 slot functioning, and alloca markers are being discovered correctly. DEBUG macros added to clean up the code a bit. Changed SparcInstManip to use class constants over functions that ended up never becoming virtual as originally intended. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/InstManip.h diff -u llvm/lib/Reoptimizer/Inst/lib/InstManip.h:1.15 llvm/lib/Reoptimizer/Inst/lib/InstManip.h:1.16 --- llvm/lib/Reoptimizer/Inst/lib/InstManip.h:1.15 Wed May 7 20:50:06 2003 +++ llvm/lib/Reoptimizer/Inst/lib/InstManip.h Thu May 8 11:27:25 2003 @@ -72,7 +72,7 @@ virtual void buildSlot(PrimInfo* pi, uint64_t slotBase, uint64_t instAddr, - uint64_t startAddr, + const std::pair& extents, std::vector& snippet) = 0; virtual unsigned getSlotSize(Phase2* p2) const = 0; @@ -83,8 +83,7 @@ // region defined by the given addresses. This is necessarily a platform-dependent // action. - virtual void findCandidates(uint64_t start, - uint64_t end, + virtual void findCandidates(const std::pair& range, std::vector& candidates) = 0; // getStartAddr - return the desired starting position in the function body. This is Index: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h diff -u llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.2 llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.3 --- llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.2 Wed May 7 20:50:06 2003 +++ llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h Thu May 8 11:27:25 2003 @@ -13,6 +13,13 @@ class TraceCache; class InstManip; +#define DEBUG 1 +#if DEBUG +#define DEBUG_MSG(x) std::cerr << x +#else +#define DEBUG_MSG(x) +#endif + typedef std::pair AddressRange; typedef struct PrimInfo { @@ -24,14 +31,14 @@ class Phase3Info { public: - Phase3Info(const AddressRange& addressRange, + Phase3Info(const AddressRange& range, unsigned origInst, uint64_t replaceAddr, uint64_t slotDescriptor, unsigned slotSize, TraceCache* pTC, InstManip* pIM): - m_addrRange(addressRange), + m_range(range), m_origInst(origInst), m_replaceAddr(replaceAddr), m_slotDescriptor(slotDescriptor), @@ -44,26 +51,25 @@ void print(std::ostream& ostr) { ostr << std::hex << "Phase3Info instance: {" << std::endl - << " Function address range: [" << m_addrRange.first << ", " - << m_addrRange.second << "]" << std::endl + << " Function address range: [" << m_range.first << ", " + << m_range.second << "]" << std::endl << " To replace: [" << m_origInst << " @ " << m_replaceAddr << "]" << std::endl << "}" << std::endl; } - uint64_t getStartAddr() const { return m_addrRange.first; } - uint64_t getEndAddr() const { return m_addrRange.second; } - uint64_t getOrigInst() const { return m_origInst; } - uint64_t getReplaceAddr() const { return m_replaceAddr; } - uint64_t getSlot() const { return m_slotDescriptor; } - uint64_t getSlotSize() const { return m_slotSize; } - TraceCache* getTraceCache() { return m_pTC; } - InstManip* getIM() { return m_pIM; } + const AddressRange& getRange() const { return m_range; } + uint64_t getOrigInst() const { return m_origInst; } + uint64_t getReplaceAddr() const { return m_replaceAddr; } + uint64_t getSlot() const { return m_slotDescriptor; } + uint64_t getSlotSize() const { return m_slotSize; } + TraceCache* getTraceCache() { return m_pTC; } + InstManip* getIM() { return m_pIM; } private: Phase3Info() {} - AddressRange m_addrRange; // Range of function for phase 3 to examine + AddressRange m_range; // Range of function for phase 3 to examine unsigned m_origInst; // Instruction replaced by phase 2 uint64_t m_replaceAddr; // Address at which to restore original inst uint64_t m_slotDescriptor; // Slot created by phase 2 @@ -76,13 +82,13 @@ { public: Phase4Info(const InstCandidate& candidate, - uint64_t startAddr, + const AddressRange& range, uint64_t slotDescriptor, uint64_t slotSize, TraceCache* pTC, InstManip* pIM): m_candidate(candidate), - m_startAddr(startAddr), + m_range(range), m_slotDescriptor(slotDescriptor), m_slotSize(slotSize), m_pTC(pTC), @@ -90,18 +96,18 @@ { } - const InstCandidate& getCandidate() const { return m_candidate; } - uint64_t getStartAddr() const { return m_startAddr; } - uint64_t getSlot() const { return m_slotDescriptor; } - uint64_t getSlotSize() const { return m_slotSize; } - TraceCache* getTraceCache() { return m_pTC; } - InstManip* getIM() { return m_pIM; } + const InstCandidate& getCandidate() const { return m_candidate; } + const AddressRange& getRange() const { return m_range; } + uint64_t getSlot() const { return m_slotDescriptor; } + uint64_t getSlotSize() const { return m_slotSize; } + TraceCache* getTraceCache() { return m_pTC; } + InstManip* getIM() { return m_pIM; } private: Phase4Info() {} InstCandidate m_candidate; // Candidate responsible for this instance's creation - uint64_t m_startAddr; // Start address of enclosing function + AddressRange m_range; // Start address of enclosing function uint64_t m_slotDescriptor; // Slot created by phase 3 unsigned m_slotSize; // Size of slot created by phase 3 TraceCache* m_pTC; // TraceCache instance used by phases 2 and 3 Index: llvm/lib/Reoptimizer/Inst/lib/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.24 llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.25 --- llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.24 Wed May 7 20:50:06 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phases.cpp Thu May 8 11:27:25 2003 @@ -66,14 +66,6 @@ #include "PhaseInfo.h" #include "SparcInstManip.h" -#define DEBUG 1 - -#if DEBUG -#define DEBUG_MSG(x) std::cerr << x << std::endl -#else -#define DEBUG_MSG(x) -#endif - using std::vector; using std::cerr; using std::endl; @@ -169,10 +161,10 @@ void Phase2::transform() { - DEBUG_MSG("============================== Begin Phase 2 =============================="); + DEBUG_MSG("============================== Begin Phase 2 ==============================\n"); const char* execName = getexecname(); - DEBUG_MSG("Executable name is: " << execName); + DEBUG_MSG("Executable name is: " << execName << endl); ElfReader elfReader(execName); @@ -199,13 +191,13 @@ //cerr << i->first << " is to be transformed" << endl; if(i->first == "fibs") { - DEBUG_MSG("Transforming function " << i->first << "..."); + DEBUG_MSG("Transforming function " << i->first << "...\n"); transformFunction(i->second); } } } - DEBUG_MSG("============================== End Phase 2 ==========================="); + DEBUG_MSG("============================== End Phase 2 ===========================\n"); } @@ -271,7 +263,7 @@ m_pIM->buildSlot(p3info, snippet); #if DEBUG - DEBUG_MSG("phase3 slot instructions:"); + DEBUG_MSG("phase3 slot instructions:\n"); dumpSnippet(snippet, m_pIM); #endif @@ -293,8 +285,9 @@ m_pIM(p3info->getIM()) { DEBUG_MSG("================ Begin Phase 3 [" << std::hex - << m_pPhase3Info->getStartAddr() << ", " << m_pPhase3Info->getEndAddr() - << "] ================"); + << m_pPhase3Info->getRange().first << ", " + << m_pPhase3Info->getRange().second + << "] ================\n"); // 1. Replace the original (replaced) instruction at the proper location in the // original code (thus effectively removing the branch to the slot created by phase 2 @@ -326,10 +319,10 @@ // For each load candidate, obtain a new slot and write the phase 4 slot region // contents into it. - DEBUG_MSG("There are " << candidates.size() << " candidates to process"); + DEBUG_MSG("There are " << candidates.size() << " candidates to process\n"); for(vector::iterator i = candidates.begin(), e = candidates.end(); i != e; ++i) { - DEBUG_MSG("Transforming " << *i); + DEBUG_MSG("Transforming " << *i << endl); unsigned slotSize = m_pIM->getSlotSize(this, *i); // Replace load candidate instruction with a branch to the start of a new slot. @@ -338,14 +331,14 @@ // Build the Phase4Info structure and generate the phase 4 slot. - Phase4Info* p4info = new Phase4Info(*i, m_pPhase3Info->getStartAddr(), + Phase4Info* p4info = new Phase4Info(*i, m_pPhase3Info->getRange(), slotBase, slotSize, m_pTC, m_pIM); vector snippet; m_pIM->buildSlot(p4info, snippet); #if DEBUG - DEBUG_MSG("phase4 slot instructions:"); + DEBUG_MSG("phase4 slot instructions:\n"); dumpSnippet(snippet, m_pIM); #endif @@ -361,13 +354,11 @@ { // 2. Analyze the function and determine the load-volatile candidates... vector candidates; - m_pIM->findCandidates(m_pPhase3Info->getStartAddr(), - m_pPhase3Info->getEndAddr(), - candidates); + m_pIM->findCandidates(m_pPhase3Info->getRange(), candidates); // ...and process them processCandidates(candidates); - DEBUG_MSG("============================== End Phase 3 =============================="); + DEBUG_MSG("============================== End Phase 3 ==============================\n"); } //////////////// Phase4 implementation //////////////// @@ -384,7 +375,7 @@ m_pIM(p4info->getIM()), m_tag(tag) { - DEBUG_MSG("================ Begin Phase 4 ================"); + DEBUG_MSG("================ Begin Phase 4 ================\n"); } Phase4::~Phase4() @@ -431,12 +422,12 @@ { #if DEBUG - DEBUG_MSG("tag is " << m_tag); - dumpGBT(cerr); + //dumpGBT(cerr); + DEBUG_MSG("tag is " << m_tag << ", and "); #endif if(PrimInfo* pi = searchGBT(m_tag)) { - DEBUG_MSG("Tag matches."); + DEBUG_MSG("matches.\n"); const InstCandidate& cand = m_pPhase4Info->getCandidate(); assert(cand.getInsts().size() >= 2 @@ -458,10 +449,10 @@ uint64_t slotBase = replaceInstWithBrToSlot(repAddr, slotSize, m_pTC, m_pIM); vector snippet; - m_pIM->buildSlot(pi, slotBase, repAddr, m_pPhase4Info->getStartAddr(), snippet); + m_pIM->buildSlot(pi, slotBase, repAddr, m_pPhase4Info->getRange(), snippet); #if DEBUG - DEBUG_MSG("phase 5 slot contents: "); + DEBUG_MSG("phase 5 slot contents:\n"); dumpSnippet(snippet, m_pIM); #endif @@ -479,7 +470,7 @@ #endif } else { - DEBUG_MSG("Could not find tag"); + DEBUG_MSG("does not match\n"); // The candidate failed to get elected, so pack up and go home. Restore the // replaced instruction (i.e. the branch that invoked this code) with the original // instruction at that location. @@ -497,12 +488,12 @@ m_pPhase4Info->getCandidate().front().second); #endif - DEBUG_MSG("================ End Phase 4 ================"); + DEBUG_MSG("================ End Phase 4 ================\n"); } //////////////// Phase 5 implementation //////////////// void phase5(PrimInfo* pi) { - DEBUG_MSG("phase5 function invoked"); + DEBUG_MSG("phase5 function invoked\n"); } Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.4 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.5 --- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.4 Wed May 7 20:50:06 2003 +++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp Thu May 8 11:27:25 2003 @@ -33,6 +33,24 @@ // | branch back to orig code | // | restore registers | // +---------------------------------------+ +// +// Phase 5 slot: +// NB: Slot does *not* save registers with the 'save' instruction, because +// it must perform the alloca within the stack frame of the code that +// invoked it. +// +-------------------------------------------+ +// | manually-save clobbered registers | +// | alloc spill area & inst param on stack | +// | spill shared registers | +// | copy PrimInfo ptr to param 1 | +// | copy spill area addr to param 2 | +// | call phase 5 | +// | nop | +// | restore shared registers | +// | manually-restore clobbered registers | +// | branch back to orig code | +// | nop | +// +-------------------------------------------+ // [] #include @@ -153,17 +171,18 @@ void SparcInstManip::buildSlot(PrimInfo* pi, uint64_t slotBase, uint64_t instAddr, - uint64_t startAddr, + const std::pair& extents, std::vector& snippet) { - // Before we generate code to spill the shared registers, we must first search - // backwards from the instrumentation site (i.e., the branch to the slot, formerly the + // Before we generate code to spill the shared registers, we must first search in the + // vicinity of the instrumentation site (i.e., the branch to the slot, formerly the // load-volatile) to discover a marker alloca that will tell us the correct offset in - // the current stack frame. startAddr is the starting address of the function - // containing the instrumentation site. We will search backwards from instAddr for a - // valid alloca marker, stopping at startAddr if we do not encounter one. + // the current stack frame. The search boundaries are given by the 'extents' pair, + // which is the address range of the enclosing function. - unsigned offset = findAllocaOffset(instAddr, startAddr); + unsigned offset = findAllocaOffset(instAddr, extents); + DEBUG_MSG("buildSlot(p5) obtained offset " << std::dec + << offset << std::hex << endl); startCode(snippet); @@ -225,13 +244,13 @@ return GEN_SAVE_SIZE + GEN_CALL_SIZE + GEN_BRANCH_ALWAYS_SIZE; } -void SparcInstManip::findCandidates(uint64_t start, - uint64_t end, +void SparcInstManip::findCandidates(const std::pair& range, vector& candidates) { - for(uint64_t currAddr = start; currAddr <= end; currAddr += getInstWidth()) { + for(uint64_t currAddr = range.first; + currAddr <= range.second; currAddr += getInstWidth()) { InstCandidate cand(this); - if(isCandidateLoad(currAddr, end, cand)) + if(isCandidateLoad(currAddr, range.second, cand)) candidates.push_back(cand); } } @@ -249,7 +268,7 @@ } void SparcInstManip::printRange(unsigned* start, - unsigned* end) const + unsigned* end) const { // Dumps contents (and corresponding disassembly) of memory range given by range // to stdout. TODO: Parameterize by an ostream instance; cannot do this yet @@ -348,7 +367,7 @@ } void SparcInstManip::generateParamStore(LogicalRegister src, - StackOffset off) + StackOffset off) { assert(m_pCurrSnippet && "Invalid snippet for code generation"); vector& snippet = *m_pCurrSnippet; @@ -363,7 +382,7 @@ } void SparcInstManip::generateCall(uint64_t dest, - uint64_t slotBase) + uint64_t slotBase) { assert(m_pCurrSnippet && "Invalid snippet for code generation"); vector& snippet = *m_pCurrSnippet; @@ -540,9 +559,9 @@ } bool SparcInstManip::determineSchema(InstCandidate& cand, - uint64_t end, - std::pair& load, - std::pair& store) + uint64_t end, + std::pair& load, + std::pair& store) { // inst1 contains the load instruction (the actual candidate). inst2 contains the // corresponding store instruction, which is either STB or STH. If STB, take actions @@ -597,8 +616,8 @@ } bool SparcInstManip::isCandidateLoad(uint64_t addr, - uint64_t end, - InstCandidate& cand) + uint64_t end, + InstCandidate& cand) { // {{{ Description of heuristic @@ -656,8 +675,8 @@ } uint64_t SparcInstManip::findNextStackLoad(uint64_t addr, - uint64_t end, - unsigned fpOffset) + uint64_t end, + unsigned fpOffset) { // Sweep the range of addresses starting at addr, up to end, looking for a load byte // that is loading from [%fp + fpOffset]. Return the first such instance, or 0 is such @@ -674,8 +693,8 @@ } uint64_t SparcInstManip::findNextStore(uint64_t addr, - uint64_t end, - unsigned srcReg) + uint64_t end, + unsigned srcReg) { // Sweep the range of addresses starting at addr, up to end, looking for stb or sth // instructions that are storing _from_ 'fromReg'. Return the first such instance, or @@ -690,7 +709,83 @@ return 0; } -unsigned SparcInstManip::findAllocaOffset(uint64_t instAddr, uint64_t startAddr) +bool SparcInstManip::isAllocaSignature(unsigned inst, unsigned& offset) { + if(RD_FLD(inst, INSTR_OP) == OP_2 && + RD_FLD(inst, INSTR_OP3) == OP3_ADD && + RD_FLD(inst, INSTR_I) == 1 && + RD_FLD(inst, INSTR_RS1) == R_O6 && // Src == %sp + RD_FLD(inst, INSTR_RD) != R_O6) { // Target != %sp + + // Examine the immediate value and determine if it falls into one of the two + // special cases, with an as-yet-unimplemented fallback (TODO). Stack addresses + // must be multiples of STACK_ALIGN (16 for SparcV9). We also know that the alloca + // we are concerned about is always of size STACK_ALIGN (the minimum size). The + // compiler generates an a value v = (immediate value - BIAS) such that + // + // a) v is a multiple of STACK_ALIGN -or- + // b) v - STACK_ALIGN + 1 is a multiple of STACK_ALIGN + // + // This is gross and hackish but it'll do for the time being. + + unsigned imm = RD_FLD(inst, INSTR_SIMM13); + + if(0 == (imm - BIAS) % STACK_ALIGN) { + offset = imm - BIAS; + DEBUG_MSG("Alloca marker case (a)\n"); + } + else if(0 == (imm - BIAS - STACK_ALIGN + 1) % STACK_ALIGN) { + offset = imm - BIAS - STACK_ALIGN + 1; + DEBUG_MSG("Alloca marker case (b)\n"); + } + else + assert(0 && "Alloca special cases failed, need fallback implementation"); + +#if DEBUG + DEBUG_MSG("Found alloca marker: "); + sparc_print(inst); + fflush(stdout); + DEBUG_MSG(endl); +#endif + return true; + } + + return false; +} + +unsigned SparcInstManip::findAllocaOffset(uint64_t instAddr, + const std::pair& range) +{ + // Search around the vicinity of instAddr, looking for the alloca instance (more + // specifically, the "second" part of the alloca -- the add of the "magic" offset to + // the stack pointer with a non-SP destination reg) that *must* exist if Phase 1 + // worked properly (introduced an immutable alloca). Unfortunately, we cannot + // guarantee instruction ordering, so we have to search both forwards and backwards, + // within the bounds of the function. + + uint64_t curr; + + // Search backwards from SEARCH_DELTA instructions beyond the instrumentation site (or + // the end of the function, whichever is closer). We start ahead by SEARCH_DELTA to + // catch the common case where the instruction we are looking for occurs very soon + // after the instrumentation site. + + curr = std::min(instAddr + SEARCH_DELTA * getInstWidth(), range.second); + for( ; curr >= range.first; curr -= getInstWidth()) { + unsigned inst = m_pTC->getVM()->readInstrFrmVm(curr); + unsigned offset; + if(isAllocaSignature(inst, offset)) + return offset; + } + + // Forwards from instrumentation site to function end + for(curr = instAddr + getInstWidth(); curr <= range.second; curr += getInstWidth()) { + unsigned inst = m_pTC->getVM()->readInstrFrmVm(curr); + unsigned offset; + if(isAllocaSignature(inst, offset)) + return offset; + } + + assert(0 && "Failed to find alloca marker"); return 0; } Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.5 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.6 --- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.5 Wed May 7 20:50:06 2003 +++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h Thu May 8 11:27:25 2003 @@ -34,15 +34,14 @@ virtual void buildSlot(PrimInfo* pi, uint64_t slotBase, uint64_t instAddr, - uint64_t startAddr, + const std::pair& extents, std::vector& snippet); virtual unsigned getSlotSize(Phase2* p2) const; virtual unsigned getSlotSize(Phase3* p3, InstCandidate& cand) const; virtual unsigned getSlotSize(Phase4* p4) const; - virtual void findCandidates(uint64_t start, - uint64_t end, + virtual void findCandidates(const std::pair& range, std::vector& candidates); virtual uint64_t getStartAddr(uint64_t funcStartAddr) const; @@ -108,7 +107,10 @@ uint64_t end, unsigned fpOffset); - unsigned findAllocaOffset(uint64_t instAddr, uint64_t startAddr); + unsigned findAllocaOffset(uint64_t instAddr, + const std::pair& range); + + static bool isAllocaSignature(unsigned inst, unsigned& offset); std::vector* m_pCurrSnippet; OutputToInputRegMap m_outputToInputReg; // Maps input register -> output register @@ -130,9 +132,11 @@ // Branch-always (annul bit low) instruction base (address not filled in yet) static const unsigned BRANCH_ALWAYS_BASE; - static const unsigned INST_WIDTH = 4; // In bytes - static const unsigned NOP_INST = 0x01000000; - static const unsigned BIAS = 2047; + static const unsigned INST_WIDTH = 4; // In bytes + static const unsigned NOP_INST = 0x01000000; + static const unsigned BIAS = 2047; + static const unsigned STACK_ALIGN = 16; + static const unsigned SEARCH_DELTA = 20; // Fixed sizes of generated SparcV9 assembly snippets From lattner at cs.uiuc.edu Thu May 8 13:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 13:42:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CWriter/Writer.cpp Message-ID: <200305081841.NAA18214@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CWriter: Writer.cpp updated: 1.83 -> 1.84 --- Log message: Add support for variable argument functions! --- Diffs of the changes: Index: llvm/lib/CWriter/Writer.cpp diff -u llvm/lib/CWriter/Writer.cpp:1.83 llvm/lib/CWriter/Writer.cpp:1.84 --- llvm/lib/CWriter/Writer.cpp:1.83 Sat May 3 02:11:00 2003 +++ llvm/lib/CWriter/Writer.cpp Thu May 8 13:41:45 2003 @@ -11,6 +11,7 @@ #include "llvm/Instructions.h" #include "llvm/Pass.h" #include "llvm/SymbolTable.h" +#include "llvm/Intrinsics.h" #include "llvm/SlotCalculator.h" #include "llvm/Analysis/FindUsedTypes.h" #include "llvm/Analysis/ConstantsScanner.h" @@ -117,6 +118,7 @@ void visitLoadInst (LoadInst &I); void visitStoreInst (StoreInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); + void visitVarArgInst(VarArgInst &I); void visitInstruction(Instruction &I) { std::cerr << "C Writer does not know about " << I; @@ -530,12 +532,10 @@ FoundNames.insert(I->getName()); // Otherwise, keep track of name } - // printing stdlib inclusion - //Out << "#include \n"; - // get declaration for alloca Out << "/* Provide Declarations */\n"; generateAllocaDecl(Out); + Out << "#include \n"; // Provide a definition for null if one does not already exist, // and for `bool' if not compiling with a C++ compiler. @@ -573,9 +573,10 @@ needsMalloc = true; for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { // If the function is external and the name collides don't print it. - // Sometimes the bytecode likes to have multiple "declerations" for + // Sometimes the bytecode likes to have multiple "declarations" for // external functions - if (I->hasInternalLinkage() || !MangledGlobals.count(I)){ + if ((I->hasInternalLinkage() || !MangledGlobals.count(I)) && + !I->getIntrinsicID()) { printFunctionSignature(I, true); Out << ";\n"; } @@ -1001,6 +1002,35 @@ } void CWriter::visitCallInst(CallInst &I) { + // Handle intrinsic function calls first... + if (Function *F = I.getCalledFunction()) + if (LLVMIntrinsic::ID ID = (LLVMIntrinsic::ID)F->getIntrinsicID()) { + switch (ID) { + default: assert(0 && "Unknown LLVM intrinsic!"); + case LLVMIntrinsic::va_start: + Out << "va_start((va_list)*"; + writeOperand(I.getOperand(1)); + Out << ", "; + // Output the last argument to the enclosing function... + writeOperand(&I.getParent()->getParent()->aback()); + Out << ")"; + return; + + case LLVMIntrinsic::va_end: + Out << "va_end((va_list)*"; + writeOperand(I.getOperand(1)); + Out << ")"; + return; + case LLVMIntrinsic::va_copy: + Out << "va_copy((va_list)*"; + writeOperand(I.getOperand(1)); + Out << ", (va_list)"; + writeOperand(I.getOperand(2)); + Out << ")"; + return; + } + } + const PointerType *PTy = cast(I.getCalledValue()->getType()); const FunctionType *FTy = cast(PTy->getElementType()); const Type *RetTy = FTy->getReturnType(); @@ -1122,6 +1152,15 @@ Out << "&"; printIndexingExpression(I.getPointerOperand(), I.idx_begin(), I.idx_end()); } + +void CWriter::visitVarArgInst(VarArgInst &I) { + Out << "va_arg((va_list)*"; + writeOperand(I.getOperand(0)); + Out << ", "; + printType(Out, I.getType(), "", /*ignoreName*/false, /*namedContext*/false); + Out << ")"; +} + //===----------------------------------------------------------------------===// // External Interface declaration From lattner at cs.uiuc.edu Thu May 8 14:45:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 14:45:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Message-ID: <200305081944.OAA19092@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource/UnitTests: 2003-05-07-VarArgs.c updated: 1.2 -> 1.3 --- Log message: Beef up the test a bit --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c diff -u llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.2 llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.3 --- llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.2 Wed May 7 22:15:31 2003 +++ llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Thu May 8 14:43:55 2003 @@ -17,10 +17,16 @@ s = va_arg(ap, char *); printf("string %s\n", s); break; - case 'd': /* int */ + case 'i': /* int */ d = va_arg(ap, int); printf("int %d\n", d); break; + case 'd': + printf("double %f\n", va_arg(ap, double)); + break; + case 'l': + printf("long long %lld\n", va_arg(ap, long long)); + break; case 'c': /* char */ /* need a cast here since va_arg only takes fully promoted types */ @@ -32,6 +38,9 @@ } int main() { - test("ssdcd", "abc", "def", -123, 'a', 123); + test("ssici", "abc", "def", -123, 'a', 123); + + /* test promotion & 64-bit types */ + test("ddil", 1.0, 2.0f, (short)32764, 12345677823423LL); return 0; } From lattner at cs.uiuc.edu Thu May 8 14:45:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 14:45:04 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200305081944.OAA19101@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.93 -> 1.94 --- Log message: Add support for variable argument functions! --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.93 llvm/lib/Target/X86/InstSelectSimple.cpp:1.94 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.93 Wed May 7 14:21:28 2003 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Thu May 8 14:44:13 2003 @@ -17,6 +17,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Constants.h" #include "llvm/Pass.h" +#include "llvm/Intrinsics.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/SSARegMap.h" @@ -57,8 +58,9 @@ namespace { struct ISel : public FunctionPass, InstVisitor { TargetMachine &TM; - MachineFunction *F; // The function we are compiling into - MachineBasicBlock *BB; // The current MBB we are compiling + MachineFunction *F; // The function we are compiling into + MachineBasicBlock *BB; // The current MBB we are compiling + int VarArgsFrameIndex; // FrameIndex for start of varargs area std::map RegMap; // Mapping between Val's and SSA Regs @@ -134,6 +136,7 @@ void doCall(const ValueRecord &Ret, MachineInstr *CallMI, const std::vector &Args); void visitCallInst(CallInst &I); + void visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &I); // Arithmetic operators void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass); @@ -173,6 +176,7 @@ void visitShiftInst(ShiftInst &I); void visitPHINode(PHINode &I) {} // PHI nodes handled by second pass void visitCastInst(CastInst &I); + void visitVarArgInst(VarArgInst &I); void visitInstruction(Instruction &I) { std::cerr << "Cannot instruction select: " << I; @@ -434,6 +438,12 @@ } ArgOffset += 4; // Each argument takes at least 4 bytes on the stack... } + + // If the function takes variable number of arguments, add a frame offset for + // the start of the first vararg value... this is used to expand + // llvm.va_start. + if (Fn.getFunctionType()->isVarArg()) + VarArgsFrameIndex = MFI->CreateFixedObject(1, ArgOffset); } @@ -876,6 +886,12 @@ void ISel::visitCallInst(CallInst &CI) { MachineInstr *TheCall; if (Function *F = CI.getCalledFunction()) { + // Is it an intrinsic function call? + if (LLVMIntrinsic::ID ID = (LLVMIntrinsic::ID)F->getIntrinsicID()) { + visitIntrinsicCall(ID, CI); // Special intrinsics are not handled here + return; + } + // Emit a CALL instruction with PC-relative displacement. TheCall = BuildMI(X86::CALLpcrel32, 1).addGlobalAddress(F, true); } else { // Emit an indirect call... @@ -892,6 +908,29 @@ doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args); } +void ISel::visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &CI) { + unsigned TmpReg1, TmpReg2; + switch (ID) { + case LLVMIntrinsic::va_start: + // Get the address of the first vararg value... + TmpReg1 = makeAnotherReg(Type::UIntTy); + addFrameReference(BuildMI(BB, X86::LEAr32, 5, TmpReg1), VarArgsFrameIndex); + TmpReg2 = getReg(CI.getOperand(1)); + addDirectMem(BuildMI(BB, X86::MOVrm32, 5), TmpReg2).addReg(TmpReg1); + return; + + case LLVMIntrinsic::va_end: return; // Noop on X86 + case LLVMIntrinsic::va_copy: + TmpReg1 = getReg(CI.getOperand(2)); // Get existing va_list + TmpReg2 = getReg(CI.getOperand(1)); // Get va_list* to store into + addDirectMem(BuildMI(BB, X86::MOVrm32, 5), TmpReg2).addReg(TmpReg1); + return; + + default: assert(0 && "Unknown intrinsic for X86!"); + } +} + + /// visitSimpleBinary - Implement simple binary operators for integral types... /// OperatorClass is one of: 0 for Add, 1 for Sub, 2 for And, 3 for Or, @@ -1596,6 +1635,49 @@ // Anything we haven't handled already, we can't (yet) handle at all. abort(); } + +/// visitVarArgInst - Implement the va_arg instruction... +/// +void ISel::visitVarArgInst(VarArgInst &I) { + unsigned SrcReg = getReg(I.getOperand(0)); + unsigned DestReg = getReg(I); + + // Load the va_list into a register... + unsigned VAList = makeAnotherReg(Type::UIntTy); + addDirectMem(BuildMI(BB, X86::MOVmr32, 4, VAList), SrcReg); + + unsigned Size; + switch (I.getType()->getPrimitiveID()) { + default: + std::cerr << I; + assert(0 && "Error: bad type for va_arg instruction!"); + return; + case Type::PointerTyID: + case Type::UIntTyID: + case Type::IntTyID: + Size = 4; + addDirectMem(BuildMI(BB, X86::MOVmr32, 4, DestReg), VAList); + break; + case Type::ULongTyID: + case Type::LongTyID: + Size = 8; + addDirectMem(BuildMI(BB, X86::MOVmr32, 4, DestReg), VAList); + addRegOffset(BuildMI(BB, X86::MOVmr32, 4, DestReg+1), VAList, 4); + break; + case Type::DoubleTyID: + Size = 8; + addDirectMem(BuildMI(BB, X86::FLDr64, 4, DestReg), VAList); + break; + } + + // Increment the VAList pointer... + unsigned NextVAList = makeAnotherReg(Type::UIntTy); + BuildMI(BB, X86::ADDri32, 2, NextVAList).addReg(VAList).addZImm(Size); + + // Update the VAList in memory... + addDirectMem(BuildMI(BB, X86::MOVrm32, 5), SrcReg).addReg(NextVAList); +} + // ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It // returns zero when the input is not exactly a power of two. From lattner at cs.uiuc.edu Thu May 8 15:09:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 15:09:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Assembler/2003-05-08-GlobalGEPSynthesize.llx Message-ID: <200305082008.PAA19743@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Assembler: 2003-05-08-GlobalGEPSynthesize.llx added (r1.1) --- Log message: New testcase --- Diffs of the changes: Index: llvm/test/Regression/Assembler/2003-05-08-GlobalGEPSynthesize.llx diff -c /dev/null llvm/test/Regression/Assembler/2003-05-08-GlobalGEPSynthesize.llx:1.1 *** /dev/null Thu May 8 15:08:13 2003 --- llvm/test/Regression/Assembler/2003-05-08-GlobalGEPSynthesize.llx Thu May 8 15:08:03 2003 *************** *** 0 **** --- 1,13 ---- + ; RUN: if as < %s | dis | grep cast + ; RUN: then exit 1 + ; RUN: else exit 0 + ; RUN: fi + + %GlobalArray = global [1 x int] [ int 0 ] ; <[1 x int]*> [#uses=1] + + implementation ; Functions: + + int* %foo(...) { + ret int* cast (long add (long cast ([1 x int]* %GlobalArray to long), long -4) to int*) + } + From lattner at cs.uiuc.edu Thu May 8 15:32:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 15:32:00 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Assembler/2003-05-08-GlobalGEPSynthesize.llx Message-ID: <200305082031.PAA19792@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Assembler: 2003-05-08-GlobalGEPSynthesize.llx (r1.1) removed --- Log message: Remvoe testcase that should never be implemented --- Diffs of the changes: From lattner at cs.uiuc.edu Thu May 8 15:50:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 15:50:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200305082049.PAA20013@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.94 -> 1.95 --- Log message: Add support for Add, Sub, And, Or, & Xor constant exprs --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.94 llvm/lib/Target/X86/InstSelectSimple.cpp:1.95 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.94 Thu May 8 14:44:13 2003 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Thu May 8 15:49:25 2003 @@ -203,6 +203,13 @@ void emitCastOperation(MachineBasicBlock *BB,MachineBasicBlock::iterator&IP, Value *Src, const Type *DestTy, unsigned TargetReg); + /// emitSimpleBinaryOperation - Common code shared between visitSimpleBinary + /// and constant expression support. + void emitSimpleBinaryOperation(MachineBasicBlock *BB, + MachineBasicBlock::iterator &IP, + Value *Op0, Value *Op1, + unsigned OperatorClass, unsigned TargetReg); + /// copyConstantToRegister - Output the instructions required to put the /// specified constant into the specified register. /// @@ -314,17 +321,29 @@ MachineBasicBlock::iterator &IP, Constant *C, unsigned R) { if (ConstantExpr *CE = dyn_cast(C)) { - if (CE->getOpcode() == Instruction::GetElementPtr) { + unsigned Class = 0; + switch (CE->getOpcode()) { + case Instruction::GetElementPtr: emitGEPOperation(MBB, IP, CE->getOperand(0), CE->op_begin()+1, CE->op_end(), R); return; - } else if (CE->getOpcode() == Instruction::Cast) { + case Instruction::Cast: emitCastOperation(MBB, IP, CE->getOperand(0), CE->getType(), R); return; - } - std::cerr << "Offending expr: " << C << "\n"; - assert(0 && "Constant expressions not yet handled!\n"); + case Instruction::Xor: ++Class; // FALL THROUGH + case Instruction::Or: ++Class; // FALL THROUGH + case Instruction::And: ++Class; // FALL THROUGH + case Instruction::Sub: ++Class; // FALL THROUGH + case Instruction::Add: + emitSimpleBinaryOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), + Class, R); + return; + + default: + std::cerr << "Offending expr: " << C << "\n"; + assert(0 && "Constant expressions not yet handled!\n"); + } } if (C->getType()->isIntegral()) { @@ -931,13 +950,27 @@ } +/// visitSimpleBinary - Implement simple binary operators for integral types... +/// OperatorClass is one of: 0 for Add, 1 for Sub, 2 for And, 3 for Or, 4 for +/// Xor. +void ISel::visitSimpleBinary(BinaryOperator &B, unsigned OperatorClass) { + unsigned DestReg = getReg(B); + MachineBasicBlock::iterator MI = BB->end(); + emitSimpleBinaryOperation(BB, MI, B.getOperand(0), B.getOperand(1), + OperatorClass, DestReg); +} /// visitSimpleBinary - Implement simple binary operators for integral types... /// OperatorClass is one of: 0 for Add, 1 for Sub, 2 for And, 3 for Or, /// 4 for Xor. /// -void ISel::visitSimpleBinary(BinaryOperator &B, unsigned OperatorClass) { - unsigned Class = getClassB(B.getType()); +/// emitSimpleBinaryOperation - Common code shared between visitSimpleBinary +/// and constant expression support. +void ISel::emitSimpleBinaryOperation(MachineBasicBlock *BB, + MachineBasicBlock::iterator &IP, + Value *Op0, Value *Op1, + unsigned OperatorClass,unsigned TargetReg){ + unsigned Class = getClassB(Op0->getType()); static const unsigned OpcodeTab[][4] = { // Arithmetic operators @@ -958,17 +991,16 @@ unsigned Opcode = OpcodeTab[OperatorClass][Class]; assert(Opcode && "Floating point arguments to logical inst?"); - unsigned Op0r = getReg(B.getOperand(0)); - unsigned Op1r = getReg(B.getOperand(1)); - unsigned DestReg = getReg(B); - BuildMI(BB, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1r); + unsigned Op0r = getReg(Op0, BB, IP); + unsigned Op1r = getReg(Op1, BB, IP); + BMI(BB, IP, Opcode, 2, TargetReg).addReg(Op0r).addReg(Op1r); if (isLong) { // Handle the upper 32 bits of long values... static const unsigned TopTab[] = { X86::ADCrr32, X86::SBBrr32, X86::ANDrr32, X86::ORrr32, X86::XORrr32 }; - BuildMI(BB, TopTab[OperatorClass], 2, - DestReg+1).addReg(Op0r+1).addReg(Op1r+1); + BMI(BB, IP, TopTab[OperatorClass], 2, + TargetReg+1).addReg(Op0r+1).addReg(Op1r+1); } } From lattner at cs.uiuc.edu Thu May 8 16:09:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 16:09:04 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/JIT/VM.cpp Message-ID: <200305082108.QAA20204@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/JIT: VM.cpp updated: 1.2 -> 1.3 --- Log message: assert early instead of late for unimplemented feature --- Diffs of the changes: Index: llvm/tools/lli/JIT/VM.cpp diff -u llvm/tools/lli/JIT/VM.cpp:1.2 llvm/tools/lli/JIT/VM.cpp:1.3 --- llvm/tools/lli/JIT/VM.cpp:1.2 Sun Jan 12 19:00:38 2003 +++ llvm/tools/lli/JIT/VM.cpp Thu May 8 16:08:43 2003 @@ -81,10 +81,17 @@ if (F->isExternal()) return Addr = getPointerToNamedFunction(F->getName()); - // JIT all of the functions in the module. Eventually this will JIT functions - // on demand. This has the effect of populating all of the non-external - // functions into the GlobalAddress table. + static bool isAlreadyCodeGenerating = false; + if (isAlreadyCodeGenerating) { + assert(0 && "Recursive function stubs not handled yet!"); + } + + // FIXME: JIT all of the functions in the module. Eventually this will JIT + // functions on demand. This has the effect of populating all of the + // non-external functions into the GlobalAddress table. + isAlreadyCodeGenerating = true; PM.run(getModule()); + isAlreadyCodeGenerating = false; assert(Addr && "Code generation didn't add function to GlobalAddress table!"); return Addr; From lattner at cs.uiuc.edu Thu May 8 16:35:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 16:35:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/JIT/Callback.cpp Emitter.cpp VM.h Message-ID: <200305082134.QAA20629@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/JIT: Callback.cpp updated: 1.2 -> 1.3 Emitter.cpp updated: 1.3 -> 1.4 VM.h updated: 1.2 -> 1.3 --- Log message: Improve efficiency of JIT by having it use direct function calls instead of signals to regain control from the executing code --- Diffs of the changes: Index: llvm/tools/lli/JIT/Callback.cpp diff -u llvm/tools/lli/JIT/Callback.cpp:1.2 llvm/tools/lli/JIT/Callback.cpp:1.3 --- llvm/tools/lli/JIT/Callback.cpp:1.2 Sun Jan 12 19:00:02 2003 +++ llvm/tools/lli/JIT/Callback.cpp Thu May 8 16:34:11 2003 @@ -7,63 +7,48 @@ #include "VM.h" #include "Support/Statistic.h" -#include -#include #include static VM *TheVM = 0; -static void TrapHandler(int TN, siginfo_t *SI, ucontext_t *ucp) { - assert(TN == SIGSEGV && "Should be SIGSEGV!"); +// CompilationCallback - Invoked the first time that a call site is found, +// which causes lazy compilation of the target function. +// +void VM::CompilationCallback() { +#if defined(i386) || defined(__i386__) || defined(__x86__) + unsigned *StackPtr = (unsigned*)__builtin_frame_address(0); + unsigned RetAddr = (unsigned)__builtin_return_address(0); -#ifdef REG_EIP /* this code does not compile on Sparc! */ - if (SI->si_code != SEGV_MAPERR || SI->si_addr != 0 || - ucp->uc_mcontext.gregs[REG_EIP] != 0) { - std::cerr << "Bad SEGV encountered EIP = 0x" << std::hex - << ucp->uc_mcontext.gregs[REG_EIP] << " addr = " - << SI->si_addr << "!\n"; - - struct sigaction SA; // Restore old SEGV handler... - SA.sa_handler = SIG_DFL; - SA.sa_flags = SA_NOMASK; - sigaction(SIGSEGV, &SA, 0); - return; // Should core dump now... - } + assert(StackPtr[1] == RetAddr && + "Could not find return address on the stack!"); // The call instruction should have pushed the return value onto the stack... - unsigned RefAddr = *(unsigned*)ucp->uc_mcontext.gregs[REG_ESP]; - RefAddr -= 4; // Backtrack to the reference itself... + RetAddr -= 4; // Backtrack to the reference itself... - DEBUG(std::cerr << "In SEGV handler! Addr=0x" << std::hex << RefAddr - << " ESP=0x" << ucp->uc_mcontext.gregs[REG_ESP] << std::dec + DEBUG(std::cerr << "In callback! Addr=0x" << std::hex << RetAddr + << " ESP=0x" << (unsigned)StackPtr << std::dec << ": Resolving call to function: " - << TheVM->getFunctionReferencedName((void*)RefAddr) << "\n"); + << TheVM->getFunctionReferencedName((void*)RetAddr) << "\n"); // Sanity check to make sure this really is a call instruction... - assert(((unsigned char*)RefAddr)[-1] == 0xE8 && "Not a call instr!"); + assert(((unsigned char*)RetAddr)[-1] == 0xE8 && "Not a call instr!"); - unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RefAddr); + unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RetAddr); // Rewrite the call target... so that we don't fault every time we execute // the call. - *(unsigned*)RefAddr = NewVal-RefAddr-4; - - // Change the instruction pointer to be the real target of the call... - ucp->uc_mcontext.gregs[REG_EIP] = NewVal; + *(unsigned*)RetAddr = NewVal-RetAddr-4; + // Change the return address to reexecute the call instruction... + StackPtr[1] -= 5; +#else + abort(); #endif } void VM::registerCallback() { TheVM = this; - - // Register the signal handler... - struct sigaction SA; - SA.sa_sigaction = (void (*)(int, siginfo_t*, void*))TrapHandler; - sigfillset(&SA.sa_mask); // Block all signals while codegen'ing - SA.sa_flags = SA_NOCLDSTOP|SA_SIGINFO; // Get siginfo - sigaction(SIGSEGV, &SA, 0); // Install the handler } Index: llvm/tools/lli/JIT/Emitter.cpp diff -u llvm/tools/lli/JIT/Emitter.cpp:1.3 llvm/tools/lli/JIT/Emitter.cpp:1.4 --- llvm/tools/lli/JIT/Emitter.cpp:1.3 Wed Jan 29 12:02:02 2003 +++ llvm/tools/lli/JIT/Emitter.cpp Thu May 8 16:34:11 2003 @@ -131,8 +131,11 @@ void Emitter::emitGlobalAddress(GlobalValue *V, bool isPCRelative) { if (isPCRelative) { // must be a call, this is a major hack! + // FIXME: Try looking up the function to see if it is already compiled! TheVM.addFunctionRef(CurByte, cast(V)); - emitAddress(0, isPCRelative); // Delayed resolution... + + // Delayed resolution... + emitAddress((void*)VM::CompilationCallback, isPCRelative); } else { emitAddress(TheVM.getPointerToGlobal(V), isPCRelative); } Index: llvm/tools/lli/JIT/VM.h diff -u llvm/tools/lli/JIT/VM.h:1.2 llvm/tools/lli/JIT/VM.h:1.3 --- llvm/tools/lli/JIT/VM.h:1.2 Sun Jan 12 19:00:48 2003 +++ llvm/tools/lli/JIT/VM.h Thu May 8 16:34:11 2003 @@ -50,10 +50,15 @@ /// void *getPointerToNamedFunction(const std::string &Name); + // CompilationCallback - Invoked the first time that a call site is found, + // which causes lazy compilation of the target function. + // + static void CompilationCallback(); private: static MachineCodeEmitter *createEmitter(VM &V); void setupPassManager(); void *getPointerToFunction(const Function *F); + void registerCallback(); }; From lattner at cs.uiuc.edu Thu May 8 16:45:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 16:45:02 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/JIT/Callback.cpp Emitter.cpp Message-ID: <200305082144.QAA20831@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/JIT: Callback.cpp updated: 1.3 -> 1.4 Emitter.cpp updated: 1.4 -> 1.5 --- Log message: Minor speedup by avoiding callbacks to functions already generated --- Diffs of the changes: Index: llvm/tools/lli/JIT/Callback.cpp diff -u llvm/tools/lli/JIT/Callback.cpp:1.3 llvm/tools/lli/JIT/Callback.cpp:1.4 --- llvm/tools/lli/JIT/Callback.cpp:1.3 Thu May 8 16:34:11 2003 +++ llvm/tools/lli/JIT/Callback.cpp Thu May 8 16:44:21 2003 @@ -46,7 +46,6 @@ #endif } - void VM::registerCallback() { TheVM = this; } Index: llvm/tools/lli/JIT/Emitter.cpp diff -u llvm/tools/lli/JIT/Emitter.cpp:1.4 llvm/tools/lli/JIT/Emitter.cpp:1.5 --- llvm/tools/lli/JIT/Emitter.cpp:1.4 Thu May 8 16:34:11 2003 +++ llvm/tools/lli/JIT/Emitter.cpp Thu May 8 16:44:21 2003 @@ -131,11 +131,15 @@ void Emitter::emitGlobalAddress(GlobalValue *V, bool isPCRelative) { if (isPCRelative) { // must be a call, this is a major hack! - // FIXME: Try looking up the function to see if it is already compiled! - TheVM.addFunctionRef(CurByte, cast(V)); + // Try looking up the function to see if it is already compiled! + if (void *Addr = TheVM.getPointerToGlobalIfAvailable(V)) { + emitAddress(Addr, isPCRelative); + } else { // Function has not yet been code generated! + TheVM.addFunctionRef(CurByte, cast(V)); - // Delayed resolution... - emitAddress((void*)VM::CompilationCallback, isPCRelative); + // Delayed resolution... + emitAddress((void*)VM::CompilationCallback, isPCRelative); + } } else { emitAddress(TheVM.getPointerToGlobal(V), isPCRelative); } From lattner at cs.uiuc.edu Thu May 8 16:55:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 16:55:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineCodeEmitter.h Message-ID: <200305082154.QAA20886@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineCodeEmitter.h updated: 1.6 -> 1.7 --- Log message: Add new methods for stub generation --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineCodeEmitter.h diff -u llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.6 llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.7 --- llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.6 Sun Jan 12 18:14:55 2003 +++ llvm/include/llvm/CodeGen/MachineCodeEmitter.h Thu May 8 16:53:57 2003 @@ -39,6 +39,18 @@ /// virtual void startBasicBlock(MachineBasicBlock &BB) {} + /// startFunctionStub - This callback is invoked when the JIT needs the + /// address of a function that has not been code generated yet. The StubSize + /// specifies the total size required by the stub. Stubs are not allowed to + /// have constant pools, the can only use the other emit* methods. + /// + virtual void startFunctionStub(Function &F, unsigned StubSize) {} + + /// finishFunctionStub - This callback is invoked to terminate a function + /// stub. + /// + virtual void finishFunctionStub(Function &F) {} + /// emitByte - This callback is invoked when a byte needs to be written to the /// output stream. /// From lattner at cs.uiuc.edu Thu May 8 16:55:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 16:55:04 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/MachineCodeEmitter.cpp Message-ID: <200305082154.QAA20898@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: MachineCodeEmitter.cpp updated: 1.3 -> 1.4 --- Log message: Add methods for stub function generation --- Diffs of the changes: Index: llvm/lib/CodeGen/MachineCodeEmitter.cpp diff -u llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.3 llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.4 --- llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.3 Sun Jan 12 18:22:37 2003 +++ llvm/lib/CodeGen/MachineCodeEmitter.cpp Thu May 8 16:54:18 2003 @@ -21,6 +21,13 @@ void startBasicBlock(MachineBasicBlock &BB) { std::cout << "\n--- Basic Block: " << BB.getBasicBlock()->getName()<<"\n"; } + + void startFunctionStub(Function &F, unsigned StubSize) { + std::cout << "\n--- Function stub for function: " << F.getName() << "\n"; + } + void finishFunctionStub(Function &F) { + std::cout << "\n"; + } void emitByte(unsigned char B) { std::cout << "0x" << std::hex << (unsigned int)B << std::dec << " "; From lattner at cs.uiuc.edu Thu May 8 17:02:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 17:02:02 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineCodeEmitter.h Message-ID: <200305082201.RAA21377@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineCodeEmitter.h updated: 1.7 -> 1.8 --- Log message: Fix bug in last checkin --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineCodeEmitter.h diff -u llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.7 llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.8 --- llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.7 Thu May 8 16:53:57 2003 +++ llvm/include/llvm/CodeGen/MachineCodeEmitter.h Thu May 8 17:00:52 2003 @@ -16,6 +16,7 @@ class MachineConstantPool; class Value; class GlobalValue; +class Function; struct MachineCodeEmitter { virtual ~MachineCodeEmitter() {} From lattner at cs.uiuc.edu Thu May 8 22:28:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 22:28:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineCodeEmitter.h Message-ID: <200305090327.WAA26173@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineCodeEmitter.h updated: 1.8 -> 1.9 --- Log message: Allow const functions --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineCodeEmitter.h diff -u llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.8 llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.9 --- llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.8 Thu May 8 17:00:52 2003 +++ llvm/include/llvm/CodeGen/MachineCodeEmitter.h Thu May 8 22:27:28 2003 @@ -45,12 +45,12 @@ /// specifies the total size required by the stub. Stubs are not allowed to /// have constant pools, the can only use the other emit* methods. /// - virtual void startFunctionStub(Function &F, unsigned StubSize) {} + virtual void startFunctionStub(const Function &F, unsigned StubSize) {} /// finishFunctionStub - This callback is invoked to terminate a function /// stub. /// - virtual void finishFunctionStub(Function &F) {} + virtual void *finishFunctionStub(const Function &F) { return 0; } /// emitByte - This callback is invoked when a byte needs to be written to the /// output stream. From lattner at cs.uiuc.edu Thu May 8 22:28:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 22:28:04 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/MachineCodeEmitter.cpp Message-ID: <200305090327.WAA26182@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: MachineCodeEmitter.cpp updated: 1.4 -> 1.5 --- Log message: Allow const functions --- Diffs of the changes: Index: llvm/lib/CodeGen/MachineCodeEmitter.cpp diff -u llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.4 llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.5 --- llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.4 Thu May 8 16:54:18 2003 +++ llvm/lib/CodeGen/MachineCodeEmitter.cpp Thu May 8 22:27:41 2003 @@ -22,11 +22,12 @@ std::cout << "\n--- Basic Block: " << BB.getBasicBlock()->getName()<<"\n"; } - void startFunctionStub(Function &F, unsigned StubSize) { + void startFunctionStub(const Function &F, unsigned StubSize) { std::cout << "\n--- Function stub for function: " << F.getName() << "\n"; } - void finishFunctionStub(Function &F) { + void *finishFunctionStub(const Function &F) { std::cout << "\n"; + return 0; } void emitByte(unsigned char B) { From lattner at cs.uiuc.edu Thu May 8 22:29:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 22:29:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/MachineCodeEmitter.cpp Message-ID: <200305090328.WAA26193@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: MachineCodeEmitter.cpp updated: 1.21 -> 1.22 --- Log message: This blank line has GOT to go. --- Diffs of the changes: Index: llvm/lib/Target/X86/MachineCodeEmitter.cpp diff -u llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.21 llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.22 --- llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.21 Wed May 7 14:21:28 2003 +++ llvm/lib/Target/X86/MachineCodeEmitter.cpp Thu May 8 22:28:13 2003 @@ -41,7 +41,6 @@ }; } - /// addPassesToEmitMachineCode - Add passes to the specified pass manager to get /// machine code emitted. This uses a MAchineCodeEmitter object to handle /// actually outputting the machine code and resolving things like the address From lattner at cs.uiuc.edu Thu May 8 22:30:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 22:30:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/ExecutionEngine.h Message-ID: <200305090329.WAA26204@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli: ExecutionEngine.h updated: 1.2 -> 1.3 --- Log message: Add new method to check to see if a global is available --- Diffs of the changes: Index: llvm/tools/lli/ExecutionEngine.h diff -u llvm/tools/lli/ExecutionEngine.h:1.2 llvm/tools/lli/ExecutionEngine.h:1.3 --- llvm/tools/lli/ExecutionEngine.h:1.2 Thu May 8 11:52:16 2003 +++ llvm/tools/lli/ExecutionEngine.h Thu May 8 22:29:03 2003 @@ -62,6 +62,14 @@ CurVal = Addr; } + // getPointerToGlobalIfAvailable - This returns the address of the specified + // global value if it is available, otherwise it returns null. + // + void *getPointerToGlobalIfAvailable(const GlobalValue *GV) { + std::map::iterator I = GlobalAddress.find(GV); + return I != GlobalAddress.end() ? I->second : 0; + } + // getPointerToGlobal - This returns the address of the specified global // value. This may involve code generation if it's a function. // From lattner at cs.uiuc.edu Thu May 8 22:31:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 22:31:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/JIT/Callback.cpp Emitter.cpp VM.cpp VM.h Message-ID: <200305090330.WAA26227@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/JIT: Callback.cpp updated: 1.4 -> 1.5 Emitter.cpp updated: 1.5 -> 1.6 VM.cpp updated: 1.3 -> 1.4 VM.h updated: 1.3 -> 1.4 --- Log message: Add support for function stubs, which allow calling functions which need to have an address available, but have not yet been code generated. --- Diffs of the changes: Index: llvm/tools/lli/JIT/Callback.cpp diff -u llvm/tools/lli/JIT/Callback.cpp:1.4 llvm/tools/lli/JIT/Callback.cpp:1.5 --- llvm/tools/lli/JIT/Callback.cpp:1.4 Thu May 8 16:44:21 2003 +++ llvm/tools/lli/JIT/Callback.cpp Thu May 8 22:30:07 2003 @@ -1,12 +1,14 @@ //===-- Callback.cpp - Trap handler for function resolution ---------------===// // -// This file defines the SIGSEGV handler which is invoked when a reference to a -// non-codegen'd function is found. +// This file defines the handler which is invoked when a reference to a +// non-codegen'd function is found. This file defines target specific code +// which is used by the JIT. // //===----------------------------------------------------------------------===// #include "VM.h" #include "Support/Statistic.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" #include static VM *TheVM = 0; @@ -21,6 +23,7 @@ assert(StackPtr[1] == RetAddr && "Could not find return address on the stack!"); + bool isStub = ((unsigned char*)RetAddr)[0] == 0xCD; // Interrupt marker? // The call instruction should have pushed the return value onto the stack... RetAddr -= 4; // Backtrack to the reference itself... @@ -39,8 +42,34 @@ // the call. *(unsigned*)RetAddr = NewVal-RetAddr-4; + if (isStub) { + // If this is a stub, rewrite the call into an unconditional branch + // instruction so that two return addresses are not pushed onto the stack + // when the requested function finally gets called. This also makes the + // 0xCD byte (interrupt) dead, so the marker doesn't effect anything. + ((unsigned char*)RetAddr)[-1] = 0xE9; + } + // Change the return address to reexecute the call instruction... StackPtr[1] -= 5; +#else + abort(); +#endif +} + +/// emitStubForFunction - This virtual method is used by the JIT when it needs +/// to emit the address of a function for a function whose code has not yet +/// been generated. In order to do this, it generates a stub which jumps to +/// the lazy function compiler, which will eventually get fixed to call the +/// function directly. +/// +void *VM::emitStubForFunction(const Function &F) { +#if defined(i386) || defined(__i386__) || defined(__x86__) + MCE->startFunctionStub(F, 6); + MCE->emitByte(0xE8); // Call with 32 bit pc-rel destination... + MCE->emitGlobalAddress((GlobalValue*)&F, true); + MCE->emitByte(0xCD); // Interrupt - Just a marker identifying the stub! + return MCE->finishFunctionStub(F); #else abort(); #endif Index: llvm/tools/lli/JIT/Emitter.cpp diff -u llvm/tools/lli/JIT/Emitter.cpp:1.5 llvm/tools/lli/JIT/Emitter.cpp:1.6 --- llvm/tools/lli/JIT/Emitter.cpp:1.5 Thu May 8 16:44:21 2003 +++ llvm/tools/lli/JIT/Emitter.cpp Thu May 8 22:30:07 2003 @@ -19,8 +19,11 @@ class Emitter : public MachineCodeEmitter { VM &TheVM; - unsigned char *CurBlock; - unsigned char *CurByte; + unsigned char *CurBlock, *CurByte; + + // When outputting a function stub in the context of some other function, we + // save CurBlock and CurByte here. + unsigned char *SavedCurBlock, *SavedCurByte; std::vector > BBRefs; std::map BBLocations; @@ -32,6 +35,8 @@ virtual void finishFunction(MachineFunction &F); virtual void emitConstantPool(MachineConstantPool *MCP); virtual void startBasicBlock(MachineBasicBlock &BB); + virtual void startFunctionStub(const Function &F, unsigned StubSize); + virtual void* finishFunctionStub(const Function &F); virtual void emitByte(unsigned char B); virtual void emitPCRelativeDisp(Value *V); virtual void emitGlobalAddress(GlobalValue *V, bool isPCRelative); @@ -52,14 +57,16 @@ #include #include -static void *getMemory() { - return mmap(0, 4096*8, PROT_READ|PROT_WRITE|PROT_EXEC, +// FIXME: This should be rewritten to support a real memory manager for +// executable memory pages! +static void *getMemory(unsigned NumPages) { + return mmap(0, 4096*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); } void Emitter::startFunction(MachineFunction &F) { - CurBlock = (unsigned char *)getMemory(); + CurBlock = (unsigned char *)getMemory(8); CurByte = CurBlock; // Start writing at the beginning of the fn. TheVM.addGlobalMapping(F.getFunction(), CurBlock); } @@ -99,6 +106,24 @@ BBLocations[BB.getBasicBlock()] = (unsigned)(intptr_t)CurByte; } + +void Emitter::startFunctionStub(const Function &F, unsigned StubSize) { + SavedCurBlock = CurBlock; SavedCurByte = CurByte; + // FIXME: this is a huge waste of memory. + CurBlock = (unsigned char *)getMemory((StubSize+4095)/4096); + CurByte = CurBlock; // Start writing at the beginning of the fn. +} + +void *Emitter::finishFunctionStub(const Function &F) { + NumBytes += CurByte-CurBlock; + DEBUG(std::cerr << "Finished CodeGen of [0x" << std::hex + << (unsigned)(intptr_t)CurBlock + << std::dec << "] Function stub for: " << F.getName() + << ": " << CurByte-CurBlock << " bytes of text\n"); + std::swap(CurBlock, SavedCurBlock); + CurByte = SavedCurByte; + return SavedCurBlock; +} void Emitter::emitByte(unsigned char B) { *CurByte++ = B; // Write the byte to memory Index: llvm/tools/lli/JIT/VM.cpp diff -u llvm/tools/lli/JIT/VM.cpp:1.3 llvm/tools/lli/JIT/VM.cpp:1.4 --- llvm/tools/lli/JIT/VM.cpp:1.3 Thu May 8 16:08:43 2003 +++ llvm/tools/lli/JIT/VM.cpp Thu May 8 22:30:07 2003 @@ -83,7 +83,10 @@ static bool isAlreadyCodeGenerating = false; if (isAlreadyCodeGenerating) { - assert(0 && "Recursive function stubs not handled yet!"); + // Generate a function stub instead of reentering... + void *SAddr = emitStubForFunction(*F); + assert(SAddr && "Target machine doesn't support function stub generation!"); + return SAddr; } // FIXME: JIT all of the functions in the module. Eventually this will JIT Index: llvm/tools/lli/JIT/VM.h diff -u llvm/tools/lli/JIT/VM.h:1.3 llvm/tools/lli/JIT/VM.h:1.4 --- llvm/tools/lli/JIT/VM.h:1.3 Thu May 8 16:34:11 2003 +++ llvm/tools/lli/JIT/VM.h Thu May 8 22:30:07 2003 @@ -60,6 +60,14 @@ void *getPointerToFunction(const Function *F); void registerCallback(); + + /// emitStubForFunction - This method is used by the JIT when it needs to emit + /// the address of a function for a function whose code has not yet been + /// generated. In order to do this, it generates a stub which jumps to the + /// lazy function compiler, which will eventually get fixed to call the + /// function directly. + /// + void *emitStubForFunction(const Function &F); }; #endif From lattner at cs.uiuc.edu Thu May 8 22:43:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 22:43:00 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Olden-power/main.c Message-ID: <200305090342.WAA27718@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Olden-power: main.c updated: 1.4 -> 1.5 --- Log message: Reduce the precision of the floating point numbers that are printed so that minor precision differences will not affect the diffs --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/Olden-power/main.c diff -u llvm/test/Programs/MultiSource/Olden-power/main.c:1.4 llvm/test/Programs/MultiSource/Olden-power/main.c:1.5 --- llvm/test/Programs/MultiSource/Olden-power/main.c:1.4 Wed Mar 6 17:54:06 2002 +++ llvm/test/Programs/MultiSource/Olden-power/main.c Thu May 8 22:42:24 2003 @@ -74,7 +74,7 @@ while (!finished) { Compute_Tree(r); - printf("TR=%f, TI=%f, P0=%f, Q0=%f\n", + printf("TR=%4.2f, TI=%4.2f, P0=%4.2f, Q0=%4.2f\n", r->theta_R,r->theta_I,r->D.P,r->D.Q); if (fabs(r->D.P/10000.0 - r->theta_R) < ROOT_EPSILON && fabs(r->D.Q/10000.0 - r->theta_I) < ROOT_EPSILON) { @@ -92,7 +92,7 @@ d_theta_I = -(r->theta_I - r->D.Q/10000.0) / (1 - (map_Q[i+1] - map_Q[i]) / (PER_INDEX_I * 10000.0)); - printf("D TR-%f, TI=%f\n", d_theta_R,d_theta_I); + printf("D TR-%4.2f, TI=%4.2f\n", d_theta_R,d_theta_I); r->last.P = r->D.P; r->last.Q = r->D.Q; r->last_theta_R = r->theta_R; From lattner at cs.uiuc.edu Thu May 8 22:50:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 22:50:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/llubenchmark/ Message-ID: <200305090349.WAA27840@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/llubenchmark: --- Log message: Directory /home/vadve/vadve/Research/DynOpt/CVSRepository/llvm/test/Programs/MultiSource/llubenchmark added to the repository --- Diffs of the changes: From lattner at cs.uiuc.edu Thu May 8 22:51:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 22:51:00 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/llubenchmark/Makefile llubenchmark.c Message-ID: <200305090350.WAA27868@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/llubenchmark: Makefile added (r1.1) llubenchmark.c added (r1.1) --- Log message: Initial checkin of llu benchmark --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/llubenchmark/Makefile diff -c /dev/null llvm/test/Programs/MultiSource/llubenchmark/Makefile:1.1 *** /dev/null Thu May 8 22:50:01 2003 --- llvm/test/Programs/MultiSource/llubenchmark/Makefile Thu May 8 22:49:51 2003 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../../.. + + PROG = llu + CPPFLAGS = + LDFLAGS = + + include ../Makefile.multisrc Index: llvm/test/Programs/MultiSource/llubenchmark/llubenchmark.c diff -c /dev/null llvm/test/Programs/MultiSource/llubenchmark/llubenchmark.c:1.1 *** /dev/null Thu May 8 22:50:01 2003 --- llvm/test/Programs/MultiSource/llubenchmark/llubenchmark.c Thu May 8 22:49:51 2003 *************** *** 0 **** --- 1,187 ---- + /* + * LLUBENCHMARK + * Craig Zilles (zilles at cs.wisc.edu) + * http://www.cs.wisc.edu/~zilles/llubenchmark.html + * + * This program is a linked list traversal micro-benchmark, which can + * be used (among other things) to approximate the non-benchmark + * Health. + * + * The benchmark executes for a proscribed number of iterations (-i), + * and on every iteration the lists are traversed and potentially + * extended. The number of lists can be specified (-n) as well as the + * size of the elements in the list (-s). The initial length of the + * lists can be set (-l) as well as the growth rate (-g). The growth + * rate must be non-negative, but can be a floating point number, in + * which case random numbers are used to determine whether a list is + * extended on a particular cycle (all lists are extended + * independently). If the -t option is specified, the insertion + * occurs at the tail, otherwise at the head. If the -d option is + * specified, the elements are dirtied during the traversal (which + * will necessitate a write-back when the data is evicted from the + * cache). + * + * To approximate the non-benchmark Health, use the options: + * -i -g .333 -d -t -n 341 + * + * (the growth rate of the lists in health is different for different + * levels of the hierarchy and the constant .333 is just my + * approximation of the growth rate). + * + */ + + #include + #include + #if 0 + #include + #else + #define assert(x) + #endif + + /* This file should compile stand alone */ + + struct element { + struct element *next; + int count; + }; + + void + usage(char *name) { + printf("%s:\n", name); + printf("-i \n"); + printf("[-l ] (default 1)\n"); + printf("[-n <(N)umber of lists>] (default 1 list)\n"); + printf("[-s <(S)ize of element>] (default 32 bytes)\n"); + printf("[-g <(G)rowth rate per list, in elements per iteration>] (default 0)\n"); + printf("[-d] ((D)irty each element during traversal, default off)\n"); + printf("[-t] (insert at (T)ail of list, default off)\n"); + } + + #define ALLOC_SIZE 127 /* pick wierd num to break strides */ + struct element *free_list = NULL; + int next_free = ALLOC_SIZE; + int element_size = 32; + int num_allocated = 0; + + #if 1 + struct element * + allocate() { + if (next_free == ALLOC_SIZE) { + next_free = 0; + free_list = (struct element *) malloc (ALLOC_SIZE * element_size); + assert(free_list != 0); + } + num_allocated ++; + return (struct element *) + (((char *)free_list) + ((next_free ++) * element_size)); + } + #else + struct element * allocate() { + num_allocated ++; + return (struct element*)malloc(sizeof(struct element)); + } + #endif + + int + main(int argc, char *argv[]) { + int max_iterations = 1000, + dirty = 1, + num_lists = 196, + tail = 1, + initial_length = 1; + float growth_rate = 0.333; + char c = 0; + int i = 0, j = 0, k = 0; + int accumulate = 0; + + struct element **lists = NULL; + float growth = 0.0; + + int arg = 1; + + printf("This benchmark modified to not use hard coded pool allocation!\n"); + while (arg < argc) { + if ((argv[arg][0] != '-') || (argv[arg][2] != 0)) { + printf("parse error in %s\n", argv[arg]); + usage(argv[0]); + return(-1); + } + c = argv[arg][1]; + arg ++; + switch(c) { + case 'd': dirty = 1; break; + case 'g': growth_rate = atof(argv[arg++]); break; + case 'i': max_iterations = atoi(argv[arg++]); break; + case 'l': initial_length = atoi(argv[arg++]); break; + case 'n': num_lists = atoi(argv[arg++]); break; + case 's': element_size = atoi(argv[arg++]); break; + case 't': tail = 1; break; + default: + printf("unrecognized option: %c\n", c); + usage(argv[0]); + return(-1); + } + } + + assert (element_size > sizeof(struct element)); + assert (initial_length > 0); + + /* build lists */ + lists = (struct element **) malloc (num_lists * sizeof(struct element *)); + assert(lists != 0); + + for (i = 0 ; i < num_lists ; i ++) { + lists[i] = NULL; + } + + + for (i = 0 ; i < initial_length ; i ++) { + for (j = 0 ; j < num_lists ; j ++) { + struct element *e = allocate(); + e->next = lists[j]; + lists[j] = e; + } + } + + /* iterate */ + for (i = 0 ; i < max_iterations ; i ++) { + if ((i % 10) == 0) { + printf("%d\n", i); + } + /* traverse lists */ + for (j = 0 ; j < num_lists ; j ++) { + struct element *trav = lists[j]; + while (trav != NULL) { + accumulate += trav->count; + if (dirty) { + trav->count ++; + } + trav = trav->next; + } + } + + /* grow lists */ + growth += growth_rate; + j = growth; + growth -= j; + for ( ; j > 0 ; j --) { + for (k = 0 ; k < num_lists ; k ++) { + struct element *e = allocate(); + if (tail) { + struct element *trav = lists[k]; + while (trav->next != NULL) { + trav = trav->next; + } + trav->next = e; + e->next = NULL; + } else { + e->next = lists[k]; + lists[k] = e; + } + } + } + } + printf ("num allocated %d\n", num_allocated); + return 0; + } + From lattner at cs.uiuc.edu Thu May 8 23:12:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 23:12:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/OptimizerEval/Makefile Message-ID: <200305090411.XAA28127@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/OptimizerEval: Makefile updated: 1.1 -> 1.2 --- Log message: Add new flag to makefile --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/OptimizerEval/Makefile diff -u llvm/test/Programs/MultiSource/OptimizerEval/Makefile:1.1 llvm/test/Programs/MultiSource/OptimizerEval/Makefile:1.2 --- llvm/test/Programs/MultiSource/OptimizerEval/Makefile:1.1 Wed Jan 23 14:25:07 2002 +++ llvm/test/Programs/MultiSource/OptimizerEval/Makefile Thu May 8 23:11:47 2003 @@ -1,7 +1,9 @@ LEVEL = ../../../.. - PROG = optimizer-eval CPPFLAGS = LDFLAGS = -lm + +# This program is a timing related test +PROGRAM_IS_NONDETERMINISTIC = 1 include ../Makefile.multisrc From lattner at cs.uiuc.edu Thu May 8 23:13:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 23:13:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile.programs Message-ID: <200305090412.XAA28146@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile.programs updated: 1.38 -> 1.39 --- Log message: Allow non-deterministic programs to not botch diffs --- Diffs of the changes: Index: llvm/test/Programs/Makefile.programs diff -u llvm/test/Programs/Makefile.programs:1.38 llvm/test/Programs/Makefile.programs:1.39 --- llvm/test/Programs/Makefile.programs:1.38 Sat May 3 00:49:03 2003 +++ llvm/test/Programs/Makefile.programs Thu May 8 23:12:12 2003 @@ -226,22 +226,27 @@ # # Rules to diff test output... # +ifdef PROGRAM_IS_NONDETERMINISTIC +# If the program is non-deterministic, just save the diff to the .diff file, +# don't print out a bunch of stuff. +HIDEDIFF = > /dev/null 2>&1 +endif + $(PROGRAMS_TO_TEST:%=Output/%.diff-lli): \ Output/%.diff-lli: Output/%.out-nat Output/%.out-lli - $(DIFFPROG) lli $* + $(DIFFPROG) lli $* $(HIDEDIFF) $(PROGRAMS_TO_TEST:%=Output/%.diff-jit): \ Output/%.diff-jit: Output/%.out-nat Output/%.out-jit - $(DIFFPROG) jit $* + $(DIFFPROG) jit $* $(HIDEDIFF) $(PROGRAMS_TO_TEST:%=Output/%.diff-llc): \ Output/%.diff-llc: Output/%.out-nat Output/%.out-llc - $(DIFFPROG) llc $* + $(DIFFPROG) llc $* $(HIDEDIFF) $(PROGRAMS_TO_TEST:%=Output/%.diff-cbe): \ Output/%.diff-cbe: Output/%.out-nat Output/%.out-cbe - $(DIFFPROG) cbe $* - + $(DIFFPROG) cbe $* $(HIDEDIFF) # Rules to support the USE_PRECOMPILED_BYTECODE setting If set, submakefiles # will not know how to make output bytecode files for the programs in this From lattner at cs.uiuc.edu Thu May 8 23:13:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 23:13:04 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/sgefa/Makefile Message-ID: <200305090412.XAA28134@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/sgefa: Makefile updated: 1.1 -> 1.2 --- Log message: Add new flag to makefile --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/sgefa/Makefile diff -u llvm/test/Programs/MultiSource/sgefa/Makefile:1.1 llvm/test/Programs/MultiSource/sgefa/Makefile:1.2 --- llvm/test/Programs/MultiSource/sgefa/Makefile:1.1 Fri May 24 16:41:07 2002 +++ llvm/test/Programs/MultiSource/sgefa/Makefile Thu May 8 23:11:50 2003 @@ -1,6 +1,8 @@ LEVEL = ../../../.. - PROG = sgefa LDFLAGS = -lm + +# This program is adversely effected by the underlying precision of the machine +PROGRAM_IS_NONDETERMINISTIC = 1 include ../Makefile.multisrc From lattner at cs.uiuc.edu Thu May 8 23:18:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 23:18:01 2003 Subject: [llvm-commits] CVS: llvm/Makefile.Linux Message-ID: <200305090417.XAA29941@apoc.cs.uiuc.edu> Changes in directory llvm: Makefile.Linux updated: 1.8 -> 1.9 --- Log message: Switch over to using the new C front-end by default. --- Diffs of the changes: Index: llvm/Makefile.Linux diff -u llvm/Makefile.Linux:1.8 llvm/Makefile.Linux:1.9 --- llvm/Makefile.Linux:1.8 Fri Jan 31 13:00:26 2003 +++ llvm/Makefile.Linux Thu May 8 23:17:06 2003 @@ -26,7 +26,8 @@ # be overriden by the Makefile.config option, and should not override it if set. # ifndef LLVMGCCDIR -LLVMGCCDIR := /home/vadve/lattner/cvs/gcc_install_x86 +LLVMGCCARCH := i686-pc-linux-gnu/3.4-llvm +LLVMGCCDIR := /home/vadve/lattner/local/x86/llvm-gcc/ endif # For now we disable running LLC output, because LLC does not generate x86 code From lattner at cs.uiuc.edu Thu May 8 23:21:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 23:21:01 2003 Subject: [llvm-commits] CVS: llvm/test/Makefile.tests Message-ID: <200305090420.XAA29959@apoc.cs.uiuc.edu> Changes in directory llvm/test: Makefile.tests updated: 1.53 -> 1.54 --- Log message: Enable the new C front-end for targets which define LLVMGCCARCH --- Diffs of the changes: Index: llvm/test/Makefile.tests diff -u llvm/test/Makefile.tests:1.53 llvm/test/Makefile.tests:1.54 --- llvm/test/Makefile.tests:1.53 Tue Jan 21 15:31:29 2003 +++ llvm/test/Makefile.tests Thu May 8 23:19:58 2003 @@ -1,9 +1,7 @@ -##-----------------------------------------------------------*-Makefile-*- +##----------------------------------------------------------*- Makefile -*-===## ## Common rules for generating, linking, and compiling via LLVM. This is ## used to implement a robust testing framework for LLVM -##------------------------------------------------------------------------ - -## NOTE: This is preliminary and will change in the future +##-------------------------------------------------------------------------===## # If the user specified a TEST= option on the command line, we do not want to do # the default testing type. Instead, we change the default target to be the @@ -40,13 +38,20 @@ # LLVM Tool Definitions... # +ifdef LLVMGCCARCH # FIXME: Remove when new CFE is used on sparc as well! +LCC = $(LLVMGCCDIR)/bin/gcc +LCC1 = $(LLVMGCCDIR)/lib/gcc-lib/$(LLVMGCCARCH)/cc1 +LGCCLD = $(TOOLS)/gccld -L$(LLVMGCCDIR)/lib/gcc-lib/$(LLVMGCCARCH) -L$(LLVMGCCDIR)/lib +else LCC = $(LLVMGCCDIR)/bin/llvm-gcc LCC1 = $(LLVMGCCDIR)/lib/gcc-lib/llvm/3.1/cc1 +LGCCLD = $(TOOLS)/gccld -L$(LLVMGCCDIR)/llvm/lib +endif + LLI = $(TOOLS)/lli LLC = $(TOOLS)/llc LAS = $(TOOLS)/as LGCCAS = $(TOOLS)/gccas -LGCCLD = $(TOOLS)/gccld -L$(LLVMGCCDIR)/llvm/lib LDIS = $(TOOLS)/dis LOPT = $(TOOLS)/opt LLINK = $(TOOLS)/link From lattner at cs.uiuc.edu Thu May 8 23:41:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 8 23:41:00 2003 Subject: [llvm-commits] CVS: llvm/www/www-index.html Message-ID: <200305090440.XAA11350@tank.cs.uiuc.edu> Changes in directory llvm/www: www-index.html updated: 1.29 -> 1.30 --- Log message: Add news entry --- Diffs of the changes: Index: llvm/www/www-index.html diff -u llvm/www/www-index.html:1.29 llvm/www/www-index.html:1.30 --- llvm/www/www-index.html:1.29 Wed May 7 16:33:09 2003 +++ llvm/www/www-index.html Thu May 8 23:40:11 2003 @@ -227,6 +227,11 @@ + + + + +
      May 8th, 2003-Switched over to the rewritten C front-end which supports variable argument functions and has no known miscompilation bugs.
      Mar 4th, 2003 - Added a new From lattner at cs.uiuc.edu Fri May 9 13:17:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 9 13:17:02 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/NoSource/Makefile Message-ID: <200305091815.NAA12440@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/NoSource: Makefile updated: 1.1 -> 1.2 --- Log message: Disable nosource tests for now --- Diffs of the changes: Index: llvm/test/Programs/NoSource/Makefile diff -u llvm/test/Programs/NoSource/Makefile:1.1 llvm/test/Programs/NoSource/Makefile:1.2 --- llvm/test/Programs/NoSource/Makefile:1.1 Thu Feb 13 16:15:14 2003 +++ llvm/test/Programs/NoSource/Makefile Fri May 9 13:15:47 2003 @@ -1,6 +1,6 @@ # NoSource Makefile: Build all subdirectories automatically LEVEL = ../../.. -PARALLEL_DIRS := $(filter-out %-disabled/, $(sort $(filter-out CVS/, $(wildcard */)))) +#PARALLEL_DIRS := $(filter-out %-disabled/, $(sort $(filter-out CVS/, $(wildcard */)))) include ${LEVEL}/Makefile.common From lattner at cs.uiuc.edu Fri May 9 13:25:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 9 13:25:01 2003 Subject: [llvm-commits] CVS: llvm/www/pubs/2002-12-LattnerMSThesis.html Message-ID: <200305091824.NAA18272@tank.cs.uiuc.edu> Changes in directory llvm/www/pubs: 2002-12-LattnerMSThesis.html added (r1.1) --- Log message: Add a paper page for ms thesis --- Diffs of the changes: Index: llvm/www/pubs/2002-12-LattnerMSThesis.html diff -c /dev/null llvm/www/pubs/2002-12-LattnerMSThesis.html:1.1 *** /dev/null Fri May 9 13:24:53 2003 --- llvm/www/pubs/2002-12-LattnerMSThesis.html Fri May 9 13:24:42 2003 *************** *** 0 **** --- 1,77 ---- + + + + LLVM: An Infrastructure for Multi-Stage Optimization + + + + +


      + + + LLVM: An Infrastructure for Multi-Stage Optimization +
      + + Chris Lattner, M.S. Thesis +

      + + +

      Abstract:

      +
      + Modern programming languages and software engineering principles are causing + increasing problems for compiler systems. Traditional approaches, which use + a simple compile-link-execute model, are unable to provide adequate application + performance under the demands of the new conditions. Traditional approaches to + interprocedural and profile-driven compilation can provide the application + performance needed, but require infeasible amounts of compilation time to build + the application.

      + + This thesis presents LLVM, a design and implementation of a compiler + infrastructure which supports a unique multi-stage optimization system. + This system is designed to support extensive interprocedural and + profile-driven optimizations, while being efficient enough for use in + commercial compiler systems.

      + + The LLVM virtual instruction set is the glue that holds the system together. It + is a low-level representation, but with high-level type information. + This provides the benefits of a low-level representation (compact + representation, wide variety of available transformations, etc.) as well as + providing high-level information to support aggressive interprocedural + optimizations at link- and post-link time. In particular, this system is + designed to support optimization in the field, both at run-time and during + otherwise unused idle time on the machine.

      + + This thesis also describes an implementation of this compiler design, the LLVM + compiler infrastructure, proving that the design is feasible. The LLVM + compiler infrastructure is a maturing and efficient system, which we show is a + good host for a variety of research. More information about LLVM can be found + on its web site at: http://llvm.cs.uiuc.edu/ +

      + +

      Published:

      +
        + "LLVM: An Infrastructure for Multi-Stage Optimization", Chris Lattner.
        + Masters Thesis, Computer Science Dept., University of Illinois at + Urbana-Champaign, Dec. 2002. +
      + +

      Download:

      + + +

      Bibtex Entry:

      +
      +   @MastersThesis{Lattner:MSThesis02,
      +     author  = {Chris Lattner},
      +     title   = {{LLVM}: An Infrastructure for Multi-Stage Optimization},
      +     school  = {Computer Science Dept., University of Illinois at Urbana-Champaign},
      +     year    = {2002},
      +     address = {Urbana, IL},
      +     month   = {Dec},
      +     note    = {{\em See {\tt http://llvm.cs.uiuc.edu}.}}
      +   }
      + 
      + + From lattner at cs.uiuc.edu Fri May 9 13:25:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 9 13:25:05 2003 Subject: [llvm-commits] CVS: llvm/www/www-index.html Message-ID: <200305091824.NAA18280@tank.cs.uiuc.edu> Changes in directory llvm/www: www-index.html updated: 1.30 -> 1.31 --- Log message: Add a paper page for ms thesis --- Diffs of the changes: Index: llvm/www/www-index.html diff -u llvm/www/www-index.html:1.30 llvm/www/www-index.html:1.31 --- llvm/www/www-index.html:1.30 Thu May 8 23:40:11 2003 +++ llvm/www/www-index.html Fri May 9 13:24:44 2003 @@ -116,7 +116,7 @@ Science Dept., Univ. of Illinois, Apr. 2003.
      -
    • "LLVM: +
    • "LLVM: An Infrastructure for Multi-Stage Optimization"
      Chris Lattner. Masters Thesis, Dec. 2002
    • From lattner at cs.uiuc.edu Fri May 9 13:26:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 9 13:26:02 2003 Subject: [llvm-commits] CVS: llvm/www/pubs/2002-12-LattnerMSThesis.html Message-ID: <200305091825.NAA18318@tank.cs.uiuc.edu> Changes in directory llvm/www/pubs: 2002-12-LattnerMSThesis.html updated: 1.1 -> 1.2 --- Log message: Test checkin --- Diffs of the changes: Index: llvm/www/pubs/2002-12-LattnerMSThesis.html diff -u llvm/www/pubs/2002-12-LattnerMSThesis.html:1.1 llvm/www/pubs/2002-12-LattnerMSThesis.html:1.2 --- llvm/www/pubs/2002-12-LattnerMSThesis.html:1.1 Fri May 9 13:24:42 2003 +++ llvm/www/pubs/2002-12-LattnerMSThesis.html Fri May 9 13:25:21 2003 @@ -3,7 +3,6 @@ LLVM: An Infrastructure for Multi-Stage Optimization -


      From lattner at cs.uiuc.edu Fri May 9 15:06:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 9 15:06:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Support/Statistic.cpp Timer.cpp Message-ID: <200305092005.PAA13888@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Support: Statistic.cpp updated: 1.7 -> 1.8 Timer.cpp updated: 1.15 -> 1.16 --- Log message: Add a new info-output-file option (hidden from --help) which is to be used by the testing scripts to avoid breaking diffs while still gathering stats. --- Diffs of the changes: Index: llvm/lib/Support/Statistic.cpp diff -u llvm/lib/Support/Statistic.cpp:1.7 llvm/lib/Support/Statistic.cpp:1.8 --- llvm/lib/Support/Statistic.cpp:1.7 Sun Feb 9 15:13:57 2003 +++ llvm/lib/Support/Statistic.cpp Fri May 9 15:05:44 2003 @@ -20,6 +20,9 @@ #include #include +// GetLibSupportInfoOutputFile - Return a file stream to print our output on... +std::ostream *GetLibSupportInfoOutputFile(); + bool DebugFlag; // DebugFlag - Exported boolean set by the -debug option unsigned StatisticBase::NumStats = 0; @@ -49,11 +52,12 @@ return std::strcmp(Name, SR.Name) < 0; } - void print(unsigned ValFieldSize, unsigned NameFieldSize) { - std::cerr << std::string(ValFieldSize-Value.length(), ' ') - << Value << " " << Name - << std::string(NameFieldSize-std::strlen(Name), ' ') - << " - " << Desc << "\n"; + void print(unsigned ValFieldSize, unsigned NameFieldSize, + std::ostream &OS) { + OS << std::string(ValFieldSize-Value.length(), ' ') + << Value << " " << Name + << std::string(NameFieldSize-std::strlen(Name), ' ') + << " - " << Desc << "\n"; } }; @@ -71,6 +75,8 @@ } if (--NumStats == 0 && AccumStats) { + std::ostream *OutStream = GetLibSupportInfoOutputFile(); + // Figure out how long the biggest Value and Name fields are... unsigned MaxNameLen = 0, MaxValLen = 0; for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) { @@ -84,18 +90,20 @@ std::stable_sort(AccumStats->begin(), AccumStats->end()); // Print out the statistics header... - std::cerr << "===" << std::string(73, '-') << "===\n" - << " ... Statistics Collected ...\n" - << "===" << std::string(73, '-') << "===\n\n"; + *OutStream << "===" << std::string(73, '-') << "===\n" + << " ... Statistics Collected ...\n" + << "===" << std::string(73, '-') << "===\n\n"; // Print all of the statistics accumulated... for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) - (*AccumStats)[i].print(MaxValLen, MaxNameLen); + (*AccumStats)[i].print(MaxValLen, MaxNameLen, *OutStream); - std::cerr << std::endl; // Flush the output stream... + *OutStream << std::endl; // Flush the output stream... // Free all accumulated statistics... delete AccumStats; AccumStats = 0; + if (OutStream != &std::cerr && OutStream != &std::cout) + delete OutStream; // Close the file... } } Index: llvm/lib/Support/Timer.cpp diff -u llvm/lib/Support/Timer.cpp:1.15 llvm/lib/Support/Timer.cpp:1.16 --- llvm/lib/Support/Timer.cpp:1.15 Thu Feb 13 10:25:28 2003 +++ llvm/lib/Support/Timer.cpp Fri May 9 15:05:44 2003 @@ -11,16 +11,23 @@ #include #include #include -#include #include #include #include +#include + +std::string LibSupportInfoOutputFilename; namespace { cl::opt TrackSpace("track-memory", cl::desc("Enable -time-passes memory " "tracking (this may be slow)"), cl::Hidden); + + cl::opt + InfoOutputFilename("info-output-file", + cl::desc("File to append -stats and -timer output to"), + cl::Hidden, cl::location(LibSupportInfoOutputFilename)); } static TimerGroup *DefaultTimerGroup = 0; @@ -161,37 +168,82 @@ // TimerGroup Implementation //===----------------------------------------------------------------------===// -static void printVal(double Val, double Total) { +// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the +// TotalWidth size, and B is the AfterDec size. +// +static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth, + std::ostream &OS) { + assert(TotalWidth >= AfterDec+1 && "Bad FP Format!"); + OS.width(TotalWidth-AfterDec-1); + char OldFill = OS.fill(); + OS.fill(' '); + OS << (int)Val; // Integer part; + OS << "."; + OS.width(AfterDec); + OS.fill('0'); + unsigned ResultFieldSize = 1; + while (AfterDec--) ResultFieldSize *= 10; + OS << (int)(Val*ResultFieldSize) % ResultFieldSize; + OS.fill(OldFill); +} + +static void printVal(double Val, double Total, std::ostream &OS) { if (Total < 1e-7) // Avoid dividing by zero... - fprintf(stderr, " ----- "); - else - fprintf(stderr, " %7.4f (%5.1f%%)", Val, Val*100/Total); + OS << " ----- "; + else { + OS << " "; + printAlignedFP(Val, 4, 7, OS); + OS << " ("; + printAlignedFP(Val*100/Total, 1, 5, OS); + OS << "%)"; + } } -void Timer::print(const Timer &Total) { +void Timer::print(const Timer &Total, std::ostream &OS) { if (Total.UserTime) - printVal(UserTime, Total.UserTime); + printVal(UserTime, Total.UserTime, OS); if (Total.SystemTime) - printVal(SystemTime, Total.SystemTime); + printVal(SystemTime, Total.SystemTime, OS); if (Total.getProcessTime()) - printVal(getProcessTime(), Total.getProcessTime()); - printVal(Elapsed, Total.Elapsed); + printVal(getProcessTime(), Total.getProcessTime(), OS); + printVal(Elapsed, Total.Elapsed, OS); - fprintf(stderr, " "); + OS << " "; - if (Total.MemUsed) - fprintf(stderr, " %8ld ", MemUsed); + if (Total.MemUsed) { + OS.width(9); + OS << MemUsed << " "; + } if (Total.PeakMem) { - if (PeakMem) - fprintf(stderr, " %8ld ", PeakMem); - else - fprintf(stderr, " "); + if (PeakMem) { + OS.width(9); + OS << PeakMem << " "; + } else + OS << " "; } - std::cerr << Name << "\n"; + OS << Name << "\n"; Started = false; // Once printed, don't print again } +// GetLibSupportInfoOutputFile - Return a file stream to print our output on... +std::ostream *GetLibSupportInfoOutputFile() { + if (LibSupportInfoOutputFilename.empty()) + return &std::cerr; + if (LibSupportInfoOutputFilename == "-") + return &std::cout; + + std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(), + std::ios_base::app); + if (!Result->good()) { + std::cerr << "Error opening info-output-file '" + << LibSupportInfoOutputFilename << " for appending!\n"; + delete Result; + return &std::cerr; + } + return Result; +} + void TimerGroup::removeTimer() { if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report... @@ -203,6 +255,8 @@ unsigned Padding = (80-Name.length())/2; if (Padding > 80) Padding = 0; // Don't allow "negative" numbers + std::ostream *OutStream = GetLibSupportInfoOutputFile(); + ++NumTimers; { // Scope to contain Total timer... don't allow total timer to drop us to // zero timers... @@ -212,38 +266,42 @@ Total.sum(TimersToPrint[i]); // Print out timing header... - std::cerr << "===" << std::string(73, '-') << "===\n" - << std::string(Padding, ' ') << Name << "\n" - << "===" << std::string(73, '-') - << "===\n Total Execution Time: "; - - // Hack for GCC 2.96... :( it doesn't support manipulators! - fprintf(stderr, "%.4f seconds (%.4f wall clock)\n\n", - Total.getProcessTime(), Total.getWallTime()); + *OutStream << "===" << std::string(73, '-') << "===\n" + << std::string(Padding, ' ') << Name << "\n" + << "===" << std::string(73, '-') + << "===\n Total Execution Time: "; + + printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream); + *OutStream << " seconds ("; + printAlignedFP(Total.getWallTime(), 4, 5, *OutStream); + *OutStream << " wall clock)\n\n"; if (Total.UserTime) - std::cerr << " ---User Time---"; + *OutStream << " ---User Time---"; if (Total.SystemTime) - std::cerr << " --System Time--"; + *OutStream << " --System Time--"; if (Total.getProcessTime()) - std::cerr << " --User+System--"; - std::cerr << " ---Wall Time---"; + *OutStream << " --User+System--"; + *OutStream << " ---Wall Time---"; if (Total.getMemUsed()) - std::cerr << " ---Mem---"; + *OutStream << " ---Mem---"; if (Total.getPeakMem()) - std::cerr << " -PeakMem-"; - std::cerr << " --- Name ---\n"; + *OutStream << " -PeakMem-"; + *OutStream << " --- Name ---\n"; // Loop through all of the timing data, printing it out... for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) - TimersToPrint[i].print(Total); + TimersToPrint[i].print(Total, *OutStream); - Total.print(Total); - std::cerr << std::endl; // Flush output + Total.print(Total, *OutStream); + *OutStream << std::endl; // Flush output } --NumTimers; TimersToPrint.clear(); + + if (OutStream != &std::cerr && OutStream != &std::cout) + delete OutStream; // Close the file... } // Delete default timer group! From lattner at cs.uiuc.edu Fri May 9 15:45:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 9 15:45:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile.programs TEST.nightly.Makefile TEST.nightly.report Message-ID: <200305092044.PAA15253@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile.programs updated: 1.39 -> 1.40 TEST.nightly.Makefile updated: 1.3 -> 1.4 TEST.nightly.report updated: 1.2 -> 1.3 --- Log message: Changes to make the nightly tester more reliable, and to report the amount of time the CBE version of the program takes. Now the testing output does not include the entire output of the programs, which may be very large. Additionally, we only run each program once in each configuration instead of twice. --- Diffs of the changes: Index: llvm/test/Programs/Makefile.programs diff -u llvm/test/Programs/Makefile.programs:1.39 llvm/test/Programs/Makefile.programs:1.40 --- llvm/test/Programs/Makefile.programs:1.39 Thu May 8 23:12:12 2003 +++ llvm/test/Programs/Makefile.programs Fri May 9 15:43:49 2003 @@ -68,7 +68,7 @@ # stack trace of a core dump. It always returns "successful" so that tests will # continue to be run. ULIMIT := ulimit -t $(RUNTIMELIMIT) -RUNSAFELY = $(ULIMIT); $(PROGDIR)/RunSafely.sh +RUNSAFELY := $(PROGDIR)/RunSafely.sh # # Targets to build for the default target... @@ -203,25 +203,32 @@ ifndef USE_PRECOMPILED_BYTECODE $(PROGRAMS_TO_TEST:%=Output/%.out-nat): \ Output/%.out-nat: Output/%.native - -$(RUNSAFELY) $< > $@ $(RUN_OPTIONS) + -$(ULIMIT); $(RUNSAFELY) $< > $@ $(RUN_OPTIONS) endif -LLI_OPTS := -q -abort-on-exception -force-interpreter=true -JIT_OPTS := -force-interpreter=false +# EXTRA_LLI_OPTS is used by the nightly tester to add arguments to invocations +# of the JIT and LLI in order to get timing info and statistics. +EXTRA_LLI_OPTS := + +LLI_OPTS := -q -abort-on-exception -force-interpreter=true $(EXTRA_LLI_OPTS) +JIT_OPTS := -force-interpreter=false $(EXTRA_LLI_OPTS) + +ifdef TIME_RUN +TIME := time -p +endif $(PROGRAMS_TO_TEST:%=Output/%.out-lli): \ Output/%.out-lli: Output/%.llvm.bc $(LLI) - -$(RUNSAFELY) $(LLI) $(LLI_OPTS) $< > $@ $(RUN_OPTIONS) - + -$(ULIMIT); $(TIME) $(RUNSAFELY) $(LLI) $(LLI_OPTS) $< > $@ $(RUN_OPTIONS) $(PROGRAMS_TO_TEST:%=Output/%.out-jit): \ Output/%.out-jit: Output/%.llvm.bc $(LLI) - -$(RUNSAFELY) $(LLI) $(JIT_OPTS) $< > $@ $(RUN_OPTIONS) + -$(ULIMIT); $(TIME) $(RUNSAFELY) $(LLI) $(JIT_OPTS) $< > $@ $(RUN_OPTIONS) $(PROGRAMS_TO_TEST:%=Output/%.out-llc): \ Output/%.out-llc: Output/%.llc - -$(RUNSAFELY) $< > $@ $(RUN_OPTIONS) + -$(ULIMIT); $(TIME) $(RUNSAFELY) $< > $@ $(RUN_OPTIONS) $(PROGRAMS_TO_TEST:%=Output/%.out-cbe): \ Output/%.out-cbe: Output/%.cbe - -$(RUNSAFELY) $< > $@ $(RUN_OPTIONS) + -$(ULIMIT); $(TIME) $(RUNSAFELY) $< > $@ $(RUN_OPTIONS) # # Rules to diff test output... Index: llvm/test/Programs/TEST.nightly.Makefile diff -u llvm/test/Programs/TEST.nightly.Makefile:1.3 llvm/test/Programs/TEST.nightly.Makefile:1.4 --- llvm/test/Programs/TEST.nightly.Makefile:1.3 Wed Jan 22 13:47:03 2003 +++ llvm/test/Programs/TEST.nightly.Makefile Fri May 9 15:43:49 2003 @@ -12,7 +12,7 @@ REPORTS_TO_GEN := compile llc cbe lli jit REPORTS_SUFFIX := $(addsuffix .report.txt, $(REPORTS_TO_GEN)) -TIMEOPT := -time-passes -stats +TIMEOPT = -time-passes -stats -info-output-file=$@.info # Compilation tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.compile.report.txt): \ @@ -53,44 +53,53 @@ # CBE tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.cbe.report.txt): \ Output/%.nightly.cbe.report.txt: Output/%.llvm.bc $(LDIS) - -($(MAKE) Output/$*.cbe) > $@ 2>&1 - @if test -f Output/$*.cbe; then echo "TEST-RESULT-cbe: YES" >> $@; fi\ + -($(MAKE) TIME_RUN=1 Output/$*.diff-cbe) > $@ 2>&1 + @if test -f Output/$*.diff-cbe; then \ + echo "TEST-RESULT-cbe: YES" >> $@;\ + echo -n "TEST-RESULT-cbe-time: " >> $@;\ + grep "^real" $@ >> $@;\ + echo >> $@;\ + else \ + echo "TEST-FAIL: cbe $(RELDIR)/$*" >> $@;\ + fi + # LLI tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.lli.report.txt): \ -Output/%.nightly.lli.report.txt: Output/%.llvm.bc Output/%.diff-lli $(LLI) +Output/%.nightly.lli.report.txt: Output/%.llvm.bc $(LLI) + -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-lli) > $@ 2>&1 @if test -e Output/$*.diff-lli; then \ - ($(ULIMIT); time -p $(LLI) -stats $(LLI_OPTS) $< $(RUN_OPTIONS)) >$@ 2>&1;\ echo "TEST-PASS: lli $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-lli-time: " >> $@;\ grep "^real" $@ >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-lli-dyninst: " >> $@;\ - grep "Number of dynamic inst" $@ >> $@;\ + grep "Number of dynamic inst" $@.info >> $@;\ echo >> $@;\ else \ echo "TEST-FAIL: lli $(RELDIR)/$*" >> $@;\ fi + - at rm -f $@.info # JIT tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.jit.report.txt): \ -Output/%.nightly.jit.report.txt: Output/%.llvm.bc Output/%.diff-jit $(LLI) - @echo > $@ # Make sure something ends up in the file... - @if test -e Output/$*.diff-jit; then \ - ($(ULIMIT); time -p $(LLI) $(JIT_OPTS) $(TIMEOPT) $< $(RUN_OPTIONS)) > $@ 2>&1;\ +Output/%.nightly.jit.report.txt: Output/%.llvm.bc $(LLI) + -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-jit) > $@ 2>&1 + @if test -f Output/$*.diff-jit; then \ echo "TEST-PASS: jit $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-jit-time: " >> $@;\ grep "^real" $@ >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-jit-comptime: " >> $@;\ - grep "Total Execution Time" $@ >> $@;\ + grep "Total Execution Time" $@.info >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-jit-machcode: " >> $@;\ - grep "bytes of machine code compiled" $@ >> $@;\ + grep "bytes of machine code compiled" $@.info >> $@;\ echo >> $@;\ else \ echo "TEST-FAIL: jit $(RELDIR)/$*" >> $@;\ fi + - at rm -f $@.info # Overall tests: just run subordinate tests $(PROGRAMS_TO_TEST:%=Output/%.$(TEST).report.txt): \ Index: llvm/test/Programs/TEST.nightly.report diff -u llvm/test/Programs/TEST.nightly.report:1.2 llvm/test/Programs/TEST.nightly.report:1.3 --- llvm/test/Programs/TEST.nightly.report:1.2 Tue Jan 21 17:07:57 2003 +++ llvm/test/Programs/TEST.nightly.report Fri May 9 15:43:49 2003 @@ -22,7 +22,7 @@ ["Instrs" , 'TEST-RESULT-compile: *([0-9]+).*Number of inst'], [], ["LLC" , "TEST-RESULT-llc: $WallTimeRE"], - ["CBE" , 'TEST-RESULT-cbe: (YES|NO)'], + ["CBE" , 'TEST-RESULT-cbe-time: real\s*([.0-9m]+)'], [], ["LLI" , 'TEST-RESULT-lli-time: real\s*([.0-9m]+)'], ["DynInstrs", 'TEST-RESULT-lli-dyninst: *([0-9]+).*Number of dynamic inst'], From lattner at cs.uiuc.edu Fri May 9 15:45:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 9 15:45:06 2003 Subject: [llvm-commits] CVS: llvm/include/Support/Timer.h Message-ID: <200305092044.PAA15265@apoc.cs.uiuc.edu> Changes in directory llvm/include/Support: Timer.h updated: 1.4 -> 1.5 --- Log message: Updates to match recent timer updates --- Diffs of the changes: Index: llvm/include/Support/Timer.h diff -u llvm/include/Support/Timer.h:1.4 llvm/include/Support/Timer.h:1.5 --- llvm/include/Support/Timer.h:1.4 Mon Nov 18 15:45:55 2002 +++ llvm/include/Support/Timer.h Fri May 9 15:44:22 2003 @@ -27,6 +27,7 @@ #include #include +#include class TimerGroup; @@ -90,7 +91,7 @@ /// print - Print the current timer to standard error, and reset the "Started" /// flag. - void print(const Timer &Total); + void print(const Timer &Total, std::ostream &OS); private: friend class TimerGroup; From lattner at cs.uiuc.edu Fri May 9 17:17:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 9 17:17:04 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Function.h Message-ID: <200305092216.RAA25939@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Function.h updated: 1.42 -> 1.43 --- Log message: Update out of date comment --- Diffs of the changes: Index: llvm/include/llvm/Function.h diff -u llvm/include/llvm/Function.h:1.42 llvm/include/llvm/Function.h:1.43 --- llvm/include/llvm/Function.h:1.42 Wed May 7 22:34:12 2003 +++ llvm/include/llvm/Function.h Fri May 9 17:16:18 2003 @@ -106,8 +106,8 @@ Function *getPrev() { return Prev; } const Function *getPrev() const { return Prev; } - /// Get the underlying elements of the Function... both the argument list and - /// basic block list are empty for external functions. + /// Get the underlying elements of the Function... the basic block list is + /// empty for external functions. /// const ArgumentListType &getArgumentList() const { return ArgumentList; } ArgumentListType &getArgumentList() { return ArgumentList; } From lattner at cs.uiuc.edu Fri May 9 17:25:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 9 17:25:00 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile Message-ID: <200305092224.RAA25980@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile updated: 1.13 -> 1.14 --- Log message: Disable nosource tests --- Diffs of the changes: Index: llvm/test/Programs/Makefile diff -u llvm/test/Programs/Makefile:1.13 llvm/test/Programs/Makefile:1.14 --- llvm/test/Programs/Makefile:1.13 Tue Feb 18 14:41:10 2003 +++ llvm/test/Programs/Makefile Fri May 9 17:24:32 2003 @@ -6,7 +6,8 @@ ##===----------------------------------------------------------------------===## LEVEL = ../.. -PARALLEL_DIRS = SingleSource MultiSource NoSource +PARALLEL_DIRS = SingleSource MultiSource + #NoSource include ${LEVEL}/test/Makefile.tests From jstanley at cs.uiuc.edu Fri May 9 20:47:00 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri May 9 20:47:00 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/iOther.h Message-ID: <200305100156.UAA26330@cypher.cs.uiuc.edu> Changes in directory llvm/include/llvm: iOther.h updated: 1.33 -> 1.34 --- Log message: Fixed comment. --- Diffs of the changes: Index: llvm/include/llvm/iOther.h diff -u llvm/include/llvm/iOther.h:1.33 llvm/include/llvm/iOther.h:1.34 --- llvm/include/llvm/iOther.h:1.33 Wed May 7 21:42:50 2003 +++ llvm/include/llvm/iOther.h Fri May 9 20:56:42 2003 @@ -53,7 +53,7 @@ CallInst(Value *F, const std::vector &Par, const std::string &Name = "", Instruction *InsertBefore = 0); - // Alternate CallInst ctors; no actuals one actual, respectively. + // Alternate CallInst ctors w/ no actuals & one actual, respectively. CallInst(Value *F, const std::string &Name = "", Instruction *InsertBefore = 0); CallInst(Value *F, Value *Actual, const std::string& Name = "", From jstanley at cs.uiuc.edu Fri May 9 22:53:00 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri May 9 22:53:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h Phases.cpp SparcInstManip.cpp SparcInstManip.h Message-ID: <200305100402.XAA27224@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib: PhaseInfo.h updated: 1.3 -> 1.4 Phases.cpp updated: 1.25 -> 1.26 SparcInstManip.cpp updated: 1.5 -> 1.6 SparcInstManip.h updated: 1.6 -> 1.7 --- Log message: Phase 5 slots are working for start-region instrumentation sites only. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h diff -u llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.3 llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.4 --- llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.3 Thu May 8 11:27:25 2003 +++ llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h Fri May 9 23:01:50 2003 @@ -26,6 +26,7 @@ unsigned gbtType; unsigned short* loadVar; unsigned gbtStartIdx; + unsigned paramSize; }; class Phase3Info Index: llvm/lib/Reoptimizer/Inst/lib/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.25 llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.26 --- llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.25 Thu May 8 11:27:25 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phases.cpp Fri May 9 23:01:50 2003 @@ -493,7 +493,10 @@ //////////////// Phase 5 implementation //////////////// -void phase5(PrimInfo* pi) +void phase5(PrimInfo* pi, void* paramMem) { DEBUG_MSG("phase5 function invoked\n"); + DEBUG_MSG("pi->paramSize == " << pi->paramSize << endl); + DEBUG_MSG("pi->loadVar (tag) == " << pi->loadVar << endl); + DEBUG_MSG("phase 5 function exiting\n"); } Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.5 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.6 --- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.5 Thu May 8 11:27:25 2003 +++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp Fri May 9 23:01:50 2003 @@ -38,19 +38,19 @@ // NB: Slot does *not* save registers with the 'save' instruction, because // it must perform the alloca within the stack frame of the code that // invoked it. -// +-------------------------------------------+ -// | manually-save clobbered registers | -// | alloc spill area & inst param on stack | -// | spill shared registers | -// | copy PrimInfo ptr to param 1 | -// | copy spill area addr to param 2 | -// | call phase 5 | -// | nop | -// | restore shared registers | -// | manually-restore clobbered registers | -// | branch back to orig code | -// | nop | -// +-------------------------------------------+ +// +------------------------------------------------------+ +// | alloc spill area/reg save/inst param region on stack | +// | manually-save clobbered registers | +// | spill shared registers | +// | copy PrimInfo ptr to param 1 | +// | copy spill area addr to param 2 | +// | call phase 5 | +// | nop | +// | restore shared registers | +// | manually-restore clobbered registers | +// | branch back to orig code | +// | nop | +// +------------------------------------------------------+ // [] #include @@ -77,7 +77,7 @@ void phase3(Phase3Info* p3info); void phase4(uint64_t tag, Phase4Info* p4info); -void phase5(PrimInfo* pi); +void phase5(PrimInfo* pi, void* paramMem); SparcInstManip::SparcInstManip(TraceCache* tc): InstManip(tc, SHARED_SIZE, INST_WIDTH, NOP_INST), @@ -155,10 +155,10 @@ generateSave(); generateAddressCopy(cand.front().second, REG_0, true); // REG_0 live to call - generateParamStore(REG_0, PARAM_0); + generateStackStore(REG_0, PARAM_0); generateSpillShared(spillAddr, REG_1, REG_2); generateLoad((uint64_t) p4info, REG_1, REG_2); // REG_1 live to call - generateParamStore(REG_1, PARAM_1); + generateStackStore(REG_1, PARAM_1); generateCall((uint64_t) &phase4, slotBase); generateRestoreShared(spillAddr); generateBranchAlways(cand.front().first, slotBase, getRestoreInst()); @@ -181,21 +181,54 @@ // which is the address range of the enclosing function. unsigned offset = findAllocaOffset(instAddr, extents); + unsigned sharedSize = WORD_WIDTH * getSharedSize(); + unsigned stkSize = sharedSize + WORD_WIDTH * 2 + pi->paramSize; + + if(stkSize % STACK_ALIGN != 0) + cerr << "Warning: not multiple of " << STACK_ALIGN << endl; + DEBUG_MSG("buildSlot(p5) obtained offset " << std::dec << offset << std::hex << endl); + // After our alloca'd stack region looks like: + // sp + BIAS + stkSize -> +--------------------------------+ + // | inst function parameter memory | } pi->paramSize + // +--------------------------------+ + // | save area for clobbered regs | } WORD_WIDTH * 2 + // +--------------------------------+ + // | spill region for shared regs | } sharedSize + // sp + BIAS + offset -> +--------------------------------+ + + // TODO: ensure that stack size is aligned properly + startCode(snippet); - generateSave(); + generateAlloca(stkSize); + + // "Manually" save REG_0, REG_1 + generateStackStore(REG_0, offset + sharedSize); + generateStackStore(REG_1, offset + sharedSize + WORD_WIDTH); + + generateSpillShared(offset); + + generateLoad((uint64_t) pi, REG_0, REG_1); // REG_0 live to call + generateStackStore(REG_0, PARAM_0); + + generateSPLoad(REG_1, offset + stkSize - pi->paramSize); // REG_1 live to call + generateStackStore(REG_1, PARAM_1); + generateCall((uint64_t) &phase5, slotBase); + generateRestoreShared(offset); - // We need to branch back to one instruction beyond instruction that branches to the - // phase 5 slot. - generateBranchAlways(instAddr + getInstWidth(), slotBase, getRestoreInst()); + // "Manually" restore REG_0, REG_1 + generateStackLoad(REG_0, offset + sharedSize); + generateStackLoad(REG_1, offset + sharedSize + WORD_WIDTH); + // We need to branch back to one instruction beyond the branch to the phase 5 slot. + generateBranchAlways(instAddr + getInstWidth(), slotBase, getNOP()); endCode(); - // TODO: Add assert against against the snippet. + // TODO: Add assert against against the snippet size. } unsigned SparcInstManip::getSlotSize(Phase2* p2) const @@ -207,10 +240,10 @@ (void) p2; return GEN_SAVE_SIZE + - GEN_SPL_SHARED_SIZE + + GEN_SPL_SIZE + GEN_LOAD_SIZE + GEN_CALL_SIZE + - GEN_RESTR_SHARED_SIZE + + GEN_UNSPL_SIZE + GEN_BRANCH_ALWAYS_SIZE; } @@ -224,12 +257,12 @@ return GEN_SAVE_SIZE + getGenAddressCopySize(cand.front().second) + - GEN_PSTORE_SIZE + - GEN_SPL_SHARED_SIZE + + GEN_STKSTORE_SIZE + + GEN_SPL_SIZE + GEN_LOAD_SIZE + - GEN_PSTORE_SIZE + + GEN_STKSTORE_SIZE + GEN_CALL_SIZE + - GEN_RESTR_SHARED_SIZE + + GEN_UNSPL_SIZE + GEN_BRANCH_ALWAYS_SIZE; } @@ -241,7 +274,20 @@ (void) p4; - return GEN_SAVE_SIZE + GEN_CALL_SIZE + GEN_BRANCH_ALWAYS_SIZE; + return GEN_ALLOCA_SIZE + + GEN_STKSTORE_SIZE + + GEN_STKSTORE_SIZE + + GEN_SPL_STK_SIZE + + GEN_LOAD_SIZE + + GEN_STKSTORE_SIZE + + GEN_SPLOAD_SIZE + + GEN_STKSTORE_SIZE + + GEN_CALL_SIZE + + GEN_STKSTORE_SIZE + + GEN_UNSPL_STK_SIZE + + GEN_STKLOAD_SIZE + + GEN_STKLOAD_SIZE + + GEN_BRANCH_ALWAYS_SIZE; } void SparcInstManip::findCandidates(const std::pair& range, @@ -292,6 +338,31 @@ fflush(stdout); } +void SparcInstManip::generateSPLoad(LogicalRegister reg, unsigned offset) +{ + // Loads the value of %sp + offset into reg + assert(m_pCurrSnippet && "Invalid snippet for code generation"); + unsigned initSize = m_pCurrSnippet->size(); + + m_pCurrSnippet->push_back(MK_ADD_R_I(m_logicalToActualReg[reg], R_O6, offset)); + + assert(m_pCurrSnippet->size() - initSize == GEN_SPLOAD_SIZE && + "Unexpected number of instructions in code sequence for SP load"); +} + +void SparcInstManip::generateAlloca(unsigned size) +{ + assert(m_pCurrSnippet && "Invalid snippet for code generation"); + assert(size % STACK_ALIGN == 0 && "SP size is not aligned"); + + unsigned initSize = m_pCurrSnippet->size(); + + m_pCurrSnippet->push_back(MK_ADD_R_I(R_O6, R_O6, -size)); + + assert(m_pCurrSnippet->size() - initSize == GEN_ALLOCA_SIZE && + "Unexpected number of instructions in code sequence for SP add"); +} + void SparcInstManip::generateLoad(uint64_t value, LogicalRegister dest, LogicalRegister tmp) @@ -366,18 +437,32 @@ "Unexpected number of instructions in code sequence for address copy"); } -void SparcInstManip::generateParamStore(LogicalRegister src, - StackOffset off) +void SparcInstManip::generateStackLoad(LogicalRegister dest, + unsigned stkOffset) { assert(m_pCurrSnippet && "Invalid snippet for code generation"); vector& snippet = *m_pCurrSnippet; unsigned initSize = snippet.size(); - unsigned srcReg = m_logicalToActualReg[src]; - snippet.push_back(MK_STX_STACK(srcReg, BIAS + off)); + snippet.push_back(MK_LDX_STACK(m_logicalToActualReg[dest], BIAS + stkOffset)); - assert(snippet.size() - initSize == GEN_PSTORE_SIZE && + assert(snippet.size() - initSize == GEN_STKSTORE_SIZE && + "Unexpected number of instructions in code sequence for parameter store"); +} + + +void SparcInstManip::generateStackStore(LogicalRegister src, + unsigned stkOffset) +{ + assert(m_pCurrSnippet && "Invalid snippet for code generation"); + vector& snippet = *m_pCurrSnippet; + + unsigned initSize = snippet.size(); + + snippet.push_back(MK_STX_STACK(m_logicalToActualReg[src], BIAS + stkOffset)); + + assert(snippet.size() - initSize == GEN_STKSTORE_SIZE && "Unexpected number of instructions in code sequence for parameter store"); } @@ -436,6 +521,34 @@ // TODO: It will be worthwhile to generate calls to functions that spill/restore the // shared registers instead of dumping all of the code into the current snippet. +static void generateRestoreShared(vector& snippet, + unsigned reg, + const unsigned width, + unsigned offset = 0) +{ + snippet.push_back(MK_LOAD_IMM(R_G1, reg, offset + 0 * width)); + snippet.push_back(MK_LOAD_IMM(R_G2, reg, offset + 1 * width)); + snippet.push_back(MK_LOAD_IMM(R_G3, reg, offset + 2 * width)); + snippet.push_back(MK_LOAD_IMM(R_G4, reg, offset + 3 * width)); + snippet.push_back(MK_LOAD_IMM(R_G5, reg, offset + 4 * width)); + snippet.push_back(MK_LOAD_IMM(R_G6, reg, offset + 5 * width)); + snippet.push_back(MK_LOAD_IMM(R_G7, reg, offset + 6 * width)); +} + +void SparcInstManip::generateRestoreShared(unsigned offset) +{ + // Un-spill from the stack -- assumes %sp + BIAS + offset points to a valid stack + // location. + + assert(m_pCurrSnippet && "Invalid snippet for code generation"); + unsigned initSize = m_pCurrSnippet->size(); + + ::generateRestoreShared(*m_pCurrSnippet, R_O6, WORD_WIDTH, offset + BIAS); + + assert(m_pCurrSnippet->size() - initSize == GEN_UNSPL_STK_SIZE && + "Unexpected number of instructions in code sequence for spill to stack"); +} + void SparcInstManip::generateRestoreShared(uint64_t restoreFromAddr, LogicalRegister tmp1, LogicalRegister tmp2) @@ -445,42 +558,57 @@ vector& snippet = *m_pCurrSnippet; unsigned initSize = snippet.size(); - unsigned tmpReg = m_logicalToActualReg[tmp1]; generateLoad(restoreFromAddr, tmp1, tmp2); - snippet.push_back(MK_LOAD_IMM(R_G1, tmpReg, 8)); - snippet.push_back(MK_LOAD_IMM(R_G2, tmpReg, 16)); - snippet.push_back(MK_LOAD_IMM(R_G3, tmpReg, 24)); - snippet.push_back(MK_LOAD_IMM(R_G4, tmpReg, 32)); - snippet.push_back(MK_LOAD_IMM(R_G5, tmpReg, 40)); - snippet.push_back(MK_LOAD_IMM(R_G6, tmpReg, 48)); - snippet.push_back(MK_LOAD_IMM(R_G7, tmpReg, 56)); + ::generateRestoreShared(snippet, m_logicalToActualReg[tmp1], WORD_WIDTH); - assert(snippet.size() - initSize == GEN_RESTR_SHARED_SIZE && + assert(snippet.size() - initSize == GEN_UNSPL_SIZE && "Unexpected number of instructions in code sequence for restore shared"); } +static void generateSpillShared(vector& snippet, + unsigned reg, + const unsigned width, + unsigned offset = 0) +{ + snippet.push_back(MK_STORE_IMM(R_G1, reg, offset + 0 * width)); + snippet.push_back(MK_STORE_IMM(R_G2, reg, offset + 1 * width)); + snippet.push_back(MK_STORE_IMM(R_G3, reg, offset + 2 * width)); + snippet.push_back(MK_STORE_IMM(R_G4, reg, offset + 3 * width)); + snippet.push_back(MK_STORE_IMM(R_G5, reg, offset + 4 * width)); + snippet.push_back(MK_STORE_IMM(R_G6, reg, offset + 5 * width)); + snippet.push_back(MK_STORE_IMM(R_G7, reg, offset + 6 * width)); +} + +void SparcInstManip::generateSpillShared(unsigned offset) +{ + // Spill to the stack -- assumes %sp + BIAS + offset points to a valid stack location, + // and that there is sufficient valid memory at %sp + BIAS + offset for the entire + // spill size. + + assert(m_pCurrSnippet && "Invalid snippet for code generation"); + unsigned initSize = m_pCurrSnippet->size(); + + ::generateSpillShared(*m_pCurrSnippet, R_O6, WORD_WIDTH, BIAS + offset); + + assert(m_pCurrSnippet->size() - initSize == GEN_SPL_STK_SIZE && + "Unexpected number of instructions in code sequence for spill to stack"); +} + void SparcInstManip::generateSpillShared(uint64_t spillToAddr, LogicalRegister tmp1, - LogicalRegister tmp2) + LogicalRegister tmp2) { assert(m_pCurrSnippet && "Invalid snippet for code generation"); assert(tmp1 != tmp2 && "Distinct logical registers required"); vector& snippet = *m_pCurrSnippet; unsigned initSize = snippet.size(); - unsigned tmpReg = m_logicalToActualReg[tmp1]; generateLoad(spillToAddr, tmp1, tmp2); - snippet.push_back(MK_STORE_IMM(R_G1, tmpReg, 8)); - snippet.push_back(MK_STORE_IMM(R_G2, tmpReg, 16)); - snippet.push_back(MK_STORE_IMM(R_G3, tmpReg, 24)); - snippet.push_back(MK_STORE_IMM(R_G4, tmpReg, 32)); - snippet.push_back(MK_STORE_IMM(R_G5, tmpReg, 40)); - snippet.push_back(MK_STORE_IMM(R_G6, tmpReg, 48)); - snippet.push_back(MK_STORE_IMM(R_G7, tmpReg, 56)); + ::generateSpillShared(snippet, m_logicalToActualReg[tmp1], WORD_WIDTH); - assert(snippet.size() - initSize == GEN_SPL_SHARED_SIZE && + assert(snippet.size() - initSize == GEN_SPL_SIZE && "Unexpected number of instructions in code sequence for spill shared"); } Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.6 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.7 --- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.6 Thu May 8 11:27:25 2003 +++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h Fri May 9 23:01:50 2003 @@ -19,12 +19,6 @@ public: SparcInstManip(TraceCache* tc); - // Offsets in stack frame for function parameters - enum StackOffset { - PARAM_0 = 128, - PARAM_1 = 136 - }; - virtual void buildSlot(Phase3Info* p3info, std::vector& snippet); @@ -67,22 +61,41 @@ void generateCall(uint64_t dest, uint64_t slotBase); + void generateSPLoad(LogicalRegister reg, unsigned offset); + + // generateAlloca - Generate code to allocate 'size' bytes on the stack + void generateAlloca(unsigned size); + void generateLoad(uint64_t value, LogicalRegister dest, LogicalRegister tmp); - void generateParamStore(LogicalRegister src, StackOffset off); + void generateStackStore(LogicalRegister src, unsigned stkOffset); + void generateStackLoad(LogicalRegister dest, unsigned stkOffset); void generateRestore(); void generateSave(); + // generateRestoreShared - Generate code to un-spill the shared registers from + // restoreFromAddr, using tmp1 and tmp2 as temporary registers + void generateRestoreShared(uint64_t restoreFromAddr, LogicalRegister tmp1 = REG_0, LogicalRegister tmp2 = REG_1); + + // generateRestoreShared - Generate code to un-spill the shared registers from the memory + // at %sp + BIAS + offset + void generateRestoreShared(unsigned offset); + // generateSpillShared - Generate code to spill the shared registers to spillFromAddr, + // using tmp1 and tmp2 as temporary registers void generateSpillShared(uint64_t spillFromAddr, LogicalRegister tmp1 = REG_0, LogicalRegister tmp2 = REG_1); + + // generateSpillShared - Generate code to spill the shared registers to the memory at + // %sp + BIAS + offset + void generateSpillShared(unsigned offset); unsigned getRestoreInst() const; inline unsigned getCallInst(uint64_t dest, uint64_t pc) const; @@ -111,7 +124,7 @@ const std::pair& range); static bool isAllocaSignature(unsigned inst, unsigned& offset); - + std::vector* m_pCurrSnippet; OutputToInputRegMap m_outputToInputReg; // Maps input register -> output register @@ -137,17 +150,24 @@ static const unsigned BIAS = 2047; static const unsigned STACK_ALIGN = 16; static const unsigned SEARCH_DELTA = 20; + static const unsigned WORD_WIDTH = 8; + static const unsigned PARAM_0 = 128; + static const unsigned PARAM_1 = PARAM_0 + 8; // Fixed sizes of generated SparcV9 assembly snippets - static const unsigned GEN_LOAD_SIZE = 6; static const unsigned GEN_CALL_SIZE = 2; static const unsigned GEN_BRANCH_ALWAYS_SIZE = 2; static const unsigned GEN_SAVE_SIZE = 1; - static const unsigned GEN_PSTORE_SIZE = 1; + static const unsigned GEN_STKSTORE_SIZE = 1; + static const unsigned GEN_STKLOAD_SIZE = 1; static const unsigned GEN_RESTORE_SIZE = 1; - static const unsigned GEN_SPL_SHARED_SIZE = GEN_LOAD_SIZE + SHARED_SIZE; - static const unsigned GEN_RESTR_SHARED_SIZE = GEN_SPL_SHARED_SIZE; + static const unsigned GEN_SPL_SIZE = GEN_LOAD_SIZE + SHARED_SIZE; + static const unsigned GEN_SPL_STK_SIZE = SHARED_SIZE; + static const unsigned GEN_UNSPL_SIZE = GEN_SPL_SIZE; + static const unsigned GEN_UNSPL_STK_SIZE = GEN_SPL_STK_SIZE; + static const unsigned GEN_ALLOCA_SIZE = 1; + static const unsigned GEN_SPLOAD_SIZE = 1; }; unsigned SparcInstManip::getBranchAlways(uint64_t dest, uint64_t pc, bool annul) const From lattner at cs.uiuc.edu Sat May 10 00:38:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 00:38:00 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/TEST.nightly.Makefile Message-ID: <200305100537.AAA06998@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: TEST.nightly.Makefile updated: 1.4 -> 1.5 --- Log message: Fix bug in previous checkin --- Diffs of the changes: Index: llvm/test/Programs/TEST.nightly.Makefile diff -u llvm/test/Programs/TEST.nightly.Makefile:1.4 llvm/test/Programs/TEST.nightly.Makefile:1.5 --- llvm/test/Programs/TEST.nightly.Makefile:1.4 Fri May 9 15:43:49 2003 +++ llvm/test/Programs/TEST.nightly.Makefile Sat May 10 00:36:58 2003 @@ -18,21 +18,22 @@ $(PROGRAMS_TO_TEST:%=Output/%.nightly.compile.report.txt): \ Output/%.nightly.compile.report.txt: Output/%.llvm.bc $(LGCCAS) @echo '$(LGCCAS) Output/$*.linked.rll -o /dev/null $(TIMEOPT) > $@ 2>&1' - @-if ($(LGCCAS) Output/$*.linked.rll -o /dev/null $(TIMEOPT) > $@ 2>&1)\ + -if ($(LGCCAS) Output/$*.linked.rll -o /dev/null $(TIMEOPT) > $@ 2>&1)\ ;then \ echo "TEST-PASS: compile $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-compile: " >> $@;\ - grep "Total Execution Time" $@ >> $@;\ + grep "Total Execution Time" $@.info >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-compile: " >> $@;\ - grep "Number of bytecode bytes written" $@ >> $@;\ + grep "Number of bytecode bytes written" $@.info >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-compile: " >> $@;\ - grep "Number of instructions" $@ >> $@;\ + grep "Number of instructions" $@.info >> $@;\ echo >> $@;\ else \ echo "TEST-FAIL: compile $(RELDIR)/$*" >> $@;\ fi + - at rm -f $@.info # LLC tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.llc.report.txt): \ @@ -41,7 +42,7 @@ @-if (time -p $(LLC) -f $(TIMEOPT) $< -o /dev/null) > $@ 2>&1; then \ echo "TEST-PASS: llc $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-llc: " >> $@;\ - grep "Total Execution Time" $@ >> $@;\ + grep "Total Execution Time" $@.info >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-llc: " >> $@;\ grep "^real" $@ >> $@;\ @@ -49,11 +50,12 @@ else \ echo "TEST-FAIL: llc $(RELDIR)/$*" >> $@;\ fi + - at rm -f $@.info # CBE tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.cbe.report.txt): \ Output/%.nightly.cbe.report.txt: Output/%.llvm.bc $(LDIS) - -($(MAKE) TIME_RUN=1 Output/$*.diff-cbe) > $@ 2>&1 + -($(MAKE) TIME_RUN=1 Output/$*.diff-cbe) 2>&1 | head -n 100 > $@ @if test -f Output/$*.diff-cbe; then \ echo "TEST-RESULT-cbe: YES" >> $@;\ echo -n "TEST-RESULT-cbe-time: " >> $@;\ @@ -67,7 +69,7 @@ # LLI tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.lli.report.txt): \ Output/%.nightly.lli.report.txt: Output/%.llvm.bc $(LLI) - -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-lli) > $@ 2>&1 + -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-lli) 2>&1 | head -n 100 > $@ @if test -e Output/$*.diff-lli; then \ echo "TEST-PASS: lli $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-lli-time: " >> $@;\ @@ -84,7 +86,7 @@ # JIT tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.jit.report.txt): \ Output/%.nightly.jit.report.txt: Output/%.llvm.bc $(LLI) - -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-jit) > $@ 2>&1 + -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-jit) 2>&1 | head -n 100 > $@ @if test -f Output/$*.diff-jit; then \ echo "TEST-PASS: jit $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-jit-time: " >> $@;\ From jstanley at cs.uiuc.edu Sat May 10 13:19:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Sat May 10 13:19:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/Phase1/ Message-ID: <200305101818.NAA26639@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib/Phase1: --- Log message: Directory /home/vadve/vadve/Research/DynOpt/CVSRepository/llvm/lib/Reoptimizer/Inst/lib/Phase1 added to the repository --- Diffs of the changes: From jstanley at cs.uiuc.edu Sat May 10 13:35:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Sat May 10 13:35:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/Makefile Message-ID: <200305101844.NAA29583@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib: Makefile updated: 1.3 -> 1.4 --- Log message: Moved Phase1 pass code into this CVS repository, fixed makefiles. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/Makefile diff -u llvm/lib/Reoptimizer/Inst/lib/Makefile:1.3 llvm/lib/Reoptimizer/Inst/lib/Makefile:1.4 --- llvm/lib/Reoptimizer/Inst/lib/Makefile:1.3 Wed Apr 30 16:54:27 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Makefile Sat May 10 13:44:32 2003 @@ -1,4 +1,5 @@ LEVEL = ../../../.. +PARALLEL_DIRS = Phase1 LIBRARYNAME = perfinst BUILD_ARCHIVE = 1 From jstanley at cs.uiuc.edu Sat May 10 13:35:05 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Sat May 10 13:35:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/Phase1/Makefile Phase1.cpp Message-ID: <200305101844.NAA29588@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib/Phase1: Makefile updated: 1.1 -> 1.2 Phase1.cpp updated: 1.23 -> 1.24 --- Log message: Moved Phase1 pass code into this CVS repository, fixed makefiles. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/Makefile diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/Makefile:1.1 llvm/lib/Reoptimizer/Inst/lib/Phase1/Makefile:1.2 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/Makefile:1.1 Wed Jan 22 12:00:09 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/Makefile Sat May 10 13:44:33 2003 @@ -1,6 +1,4 @@ -# Makefile for pcl pass - -LEVEL = $(LOCAL_CVSROOT)/llvm +LEVEL = ../../../../.. LIBRARYNAME = perf SHARED_LIBRARY = 1 Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.23 llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.24 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.23 Fri May 9 23:02:35 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp Sat May 10 13:44:33 2003 @@ -28,7 +28,6 @@ #include "llvm/Target/TargetData.h" #include "PrimInfo.h" -#include "Utils.h" using std::cerr; using std::endl; @@ -37,6 +36,15 @@ namespace pp { +static void PurgeInst(Instruction* inst) +{ + // Completely remove inst (and all its uses, recursively) + assert(inst && "PurgeInst expects non-null argument"); + while(!inst->use_empty()) + PurgeInst(dyn_cast(inst->use_back())); + inst->getParent()->getInstList().erase(inst); +} + class Phase1 : public Pass { public: @@ -389,7 +397,7 @@ startCall->getCalledFunction(), endCall->getCalledFunction())); - // Recursively remove the calls and their uses + // Remove the calls and their uses PurgeInst(startCall); PurgeInst(endCall); } @@ -428,7 +436,7 @@ m_primInfos.push_back(PrimInfo(type, php.first, metricVar, m_module, pointCall->getCalledFunction())); - // Recursively remove the call + // Remove the call PurgeInst(pointCall); } From lattner at cs.uiuc.edu Sat May 10 15:22:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 15:22:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/Interpreter/Execution.cpp Interpreter.h Message-ID: <200305102021.PAA26640@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/Interpreter: Execution.cpp updated: 1.87 -> 1.88 Interpreter.h updated: 1.27 -> 1.28 --- Log message: Fix testcase: SingleSource/UnitTests/2003-05-02-DependantPHI.c --- Diffs of the changes: Index: llvm/tools/lli/Interpreter/Execution.cpp diff -u llvm/tools/lli/Interpreter/Execution.cpp:1.87 llvm/tools/lli/Interpreter/Execution.cpp:1.88 --- llvm/tools/lli/Interpreter/Execution.cpp:1.87 Thu May 8 11:52:43 2003 +++ llvm/tools/lli/Interpreter/Execution.cpp Sat May 10 15:21:16 2003 @@ -632,38 +632,69 @@ } void Interpreter::executeBrInst(BranchInst &I, ExecutionContext &SF) { - SF.PrevBB = SF.CurBB; // Update PrevBB so that PHI nodes work... BasicBlock *Dest; Dest = I.getSuccessor(0); // Uncond branches have a fixed dest... if (!I.isUnconditional()) { Value *Cond = I.getCondition(); - GenericValue CondVal = getOperandValue(Cond, SF); - if (CondVal.BoolVal == 0) // If false cond... + if (getOperandValue(Cond, SF).BoolVal == 0) // If false cond... Dest = I.getSuccessor(1); } - SF.CurBB = Dest; // Update CurBB to branch destination - SF.CurInst = SF.CurBB->begin(); // Update new instruction ptr... + SwitchToNewBasicBlock(Dest, SF); } -static void executeSwitch(SwitchInst &I, ExecutionContext &SF) { +void Interpreter::executeSwitchInst(SwitchInst &I, ExecutionContext &SF) { GenericValue CondVal = getOperandValue(I.getOperand(0), SF); const Type *ElTy = I.getOperand(0)->getType(); - SF.PrevBB = SF.CurBB; // Update PrevBB so that PHI nodes work... - BasicBlock *Dest = 0; // Check to see if any of the cases match... - for (unsigned i = 2, e = I.getNumOperands(); i != e; i += 2) { + BasicBlock *Dest = 0; + for (unsigned i = 2, e = I.getNumOperands(); i != e; i += 2) if (executeSetEQInst(CondVal, getOperandValue(I.getOperand(i), SF), ElTy).BoolVal) { Dest = cast(I.getOperand(i+1)); break; } - } if (!Dest) Dest = I.getDefaultDest(); // No cases matched: use default - SF.CurBB = Dest; // Update CurBB to branch destination - SF.CurInst = SF.CurBB->begin(); // Update new instruction ptr... + SwitchToNewBasicBlock(Dest, SF); +} + +// SwitchToNewBasicBlock - This method is used to jump to a new basic block. +// This function handles the actual updating of block and instruction iterators +// as well as execution of all of the PHI nodes in the destination block. +// +// This method does this because all of the PHI nodes must be executed +// atomically, reading their inputs before any of the results are updated. Not +// doing this can cause problems if the PHI nodes depend on other PHI nodes for +// their inputs. If the input PHI node is updated before it is read, incorrect +// results can happen. Thus we use a two phase approach. +// +void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){ + BasicBlock *PrevBB = SF.CurBB; // Remember where we came from... + SF.CurBB = Dest; // Update CurBB to branch destination + SF.CurInst = SF.CurBB->begin(); // Update new instruction ptr... + + if (!isa(SF.CurInst)) return; // Nothing fancy to do + + // Loop over all of the PHI nodes in the current block, reading their inputs. + std::vector ResultValues; + + for (; PHINode *PN = dyn_cast(SF.CurInst); ++SF.CurInst) { + // Search for the value corresponding to this previous bb... + int i = PN->getBasicBlockIndex(PrevBB); + assert(i != -1 && "PHINode doesn't contain entry for predecessor??"); + Value *IncomingValue = PN->getIncomingValue(i); + + // Save the incoming value for this PHI node... + ResultValues.push_back(getOperandValue(IncomingValue, SF)); + } + + // Now loop over all of the PHI nodes setting their values... + SF.CurInst = SF.CurBB->begin(); + for (unsigned i = 0; PHINode *PN = dyn_cast(SF.CurInst); + ++SF.CurInst, ++i) + SetValue(PN, ResultValues[i], SF); } @@ -812,23 +843,6 @@ callFunction((Function*)GVTOP(SRC), ArgVals); } -static void executePHINode(PHINode &I, ExecutionContext &SF) { - BasicBlock *PrevBB = SF.PrevBB; - Value *IncomingValue = 0; - - // Search for the value corresponding to this previous bb... - for (unsigned i = I.getNumIncomingValues(); i > 0;) { - if (I.getIncomingBlock(--i) == PrevBB) { - IncomingValue = I.getIncomingValue(i); - break; - } - } - assert(IncomingValue && "No PHI node predecessor for current PrevBB!"); - - // Found the value, set as the result... - SetValue(&I, getOperandValue(IncomingValue, SF), SF); -} - #define IMPLEMENT_SHIFT(OP, TY) \ case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.UByteVal; break @@ -1043,8 +1057,6 @@ FuncInfo->NumPlaneElements[i]*sizeof(GenericValue)); } - StackFrame.PrevBB = 0; // No previous BB for PHI nodes... - // Run through the function arguments and initialize their values... assert((ArgVals.size() == F->asize() || @@ -1102,7 +1114,9 @@ // Terminators case Instruction::Ret: executeRetInst (cast(I), SF); break; case Instruction::Br: executeBrInst (cast(I), SF); break; - case Instruction::Switch: executeSwitch (cast(I), SF); break; + case Instruction::Switch: executeSwitchInst(cast(I), SF);break; + // Invoke not handled! + // Memory Instructions case Instruction::Alloca: case Instruction::Malloc: executeAllocInst((AllocationInst&)I, SF); break; @@ -1114,7 +1128,7 @@ // Miscellaneous Instructions case Instruction::Call: executeCallInst (cast (I), SF); break; - case Instruction::PHINode: executePHINode (cast (I), SF); break; + case Instruction::PHINode: assert(0 && "PHI nodes already handled!"); case Instruction::Cast: executeCastInst (cast (I), SF); break; case Instruction::Shl: executeShlInst (cast(I), SF); break; case Instruction::Shr: executeShrInst (cast(I), SF); break; Index: llvm/tools/lli/Interpreter/Interpreter.h diff -u llvm/tools/lli/Interpreter/Interpreter.h:1.27 llvm/tools/lli/Interpreter/Interpreter.h:1.28 --- llvm/tools/lli/Interpreter/Interpreter.h:1.27 Thu May 8 11:18:31 2003 +++ llvm/tools/lli/Interpreter/Interpreter.h Sat May 10 15:21:16 2003 @@ -23,6 +23,7 @@ class CallInst; class ReturnInst; class BranchInst; +class SwitchInst; class LoadInst; class StoreInst; class AllocationInst; @@ -70,7 +71,6 @@ std::vector Values;// ValuePlanes for each type std::vector VarArgs; // Values passed through an ellipsis - BasicBlock *PrevBB; // The previous BB or null if in first BB CallInst *Caller; // Holds the call that called subframes. // NULL if main func or debugger invoked fn AllocaHolderHandle Allocas; // Track memory allocated by alloca @@ -137,6 +137,7 @@ void executeCallInst(CallInst &I, ExecutionContext &SF); void executeRetInst(ReturnInst &I, ExecutionContext &SF); void executeBrInst(BranchInst &I, ExecutionContext &SF); + void executeSwitchInst(SwitchInst &I, ExecutionContext &SF); void executeAllocInst(AllocationInst &I, ExecutionContext &SF); GenericValue callExternalFunction(Function *F, const std::vector &ArgVals); @@ -161,6 +162,12 @@ private: // Helper functions + // SwitchToNewBasicBlock - Start execution in a new basic block and run any + // PHI nodes in the top of the block. This is used for intraprocedural + // control flow. + // + void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF); + void *getPointerToFunction(const Function *F) { return (void*)F; } // getCurrentExecutablePath() - Return the directory that the lli executable From lattner at cs.uiuc.edu Sat May 10 15:28:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 15:28:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/DiffOutput.sh Message-ID: <200305102027.PAA26754@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: DiffOutput.sh updated: 1.5 -> 1.6 --- Log message: Stop printing out the path to gdiff --- Diffs of the changes: Index: llvm/test/Programs/DiffOutput.sh diff -u llvm/test/Programs/DiffOutput.sh:1.5 llvm/test/Programs/DiffOutput.sh:1.6 --- llvm/test/Programs/DiffOutput.sh:1.5 Fri Feb 28 14:07:59 2003 +++ llvm/test/Programs/DiffOutput.sh Sat May 10 15:27:26 2003 @@ -12,7 +12,7 @@ DIFFOUTPUT=Output/$2.diff-$1 # Find gnu diff -if which gdiff 2> /dev/null +if which gdiff > /dev/null 2>&1 then DIFF=gdiff else From lattner at cs.uiuc.edu Sat May 10 15:41:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 15:41:00 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile.programs Message-ID: <200305102040.PAA27048@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile.programs updated: 1.40 -> 1.41 --- Log message: Fix handling of nondeterminisic programs so that the nightly tester doesn't think they failed. --- Diffs of the changes: Index: llvm/test/Programs/Makefile.programs diff -u llvm/test/Programs/Makefile.programs:1.40 llvm/test/Programs/Makefile.programs:1.41 --- llvm/test/Programs/Makefile.programs:1.40 Fri May 9 15:43:49 2003 +++ llvm/test/Programs/Makefile.programs Sat May 10 15:40:20 2003 @@ -53,10 +53,10 @@ # # TIMEPROG - The program used to get timing results for a program -TIMEPROG = $(PROGDIR)/TimeProgram.sh +TIMEPROG := $(PROGDIR)/TimeProgram.sh # DIFFPROG - The program used to diff the output -DIFFPROG = $(PROGDIR)/DiffOutput.sh +DIFFPROG := $(PROGDIR)/DiffOutput.sh # RUNTIMELIMIT - The number of seconds we should wait before certain events # timeout. This is overridable on the commandline. @@ -234,9 +234,8 @@ # Rules to diff test output... # ifdef PROGRAM_IS_NONDETERMINISTIC -# If the program is non-deterministic, just save the diff to the .diff file, -# don't print out a bunch of stuff. -HIDEDIFF = > /dev/null 2>&1 +# If the program is non-deterministic, just output something to $@ +DIFFPROG = echo > $@ endif $(PROGRAMS_TO_TEST:%=Output/%.diff-lli): \ From jstanley at cs.uiuc.edu Sat May 10 15:45:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Sat May 10 15:45:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp PrimInfo.cpp PrimInfo.h Message-ID: <200305102055.PAA30651@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib/Phase1: Phase1.cpp updated: 1.24 -> 1.25 PrimInfo.cpp updated: 1.10 -> 1.11 PrimInfo.h updated: 1.8 -> 1.9 --- Log message: - Removed old code segments that wrote directly into the documentation function, and got rid of "documentation function" notion completly, as it is not needed. - Removed dead Phase2 actions from PrimInfo class (the Phase 2 LLVM pass no longer exists, as it has been completely subsumed by the binary editing phases which are invoked at runtime). - Removed code that relied on the older performance-instrumentation function signatures (the signatures that required return-by-value instrumentation functions rather than functions that return void) - Removed ifdef'd-out block of code in Phase1::buildGuardedGVRead, which was wrapping global volatile reads in conditionals. This may be needed later, but it is assumed that the code is not needed. Refer back to this version for the deleted code to save time if it is needed later. - PrimInfo::buildStructInstances is now writing the address of the instrumentation functions into the appropriate field in the GBT. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.24 llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.25 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.24 Sat May 10 13:44:33 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp Sat May 10 15:54:54 2003 @@ -73,7 +73,6 @@ Function* m_counterPrimFunc; // Counter sigfun Function* m_regionPairDeclFunc; // Region-pair metric spec sigfun Function* m_metricSpecDeclFunc; // Point metric spec sigfun - Function* m_docFunc; // Documentation function GlobalVariable* m_allocAddr; // Global to store alloca result Module* m_module; // Current module vector m_primInfos; // Deferred documentation structures @@ -110,22 +109,6 @@ Constant::getNullValue(Type::UByteTy), "allocAddr", m_module); - - //////////////// - // Build documentation function to keep data persistent between phases - - params.clear(); - m_docFunc = m.getOrInsertFunction("docFunc", FunctionType::get(Type::VoidTy, params, false)); - BasicBlock* docBlock = new BasicBlock("entry", m_docFunc); - docBlock->getInstList().push_back(new ReturnInst()); - - // Place call to docFunc at entry to main so that it doesn't get optimized away. -#if 0 - Function* main = m.getMainFunction(); - assert(main && "Require existence of main to place call to doc func"); - BasicBlock::iterator entry = main->getEntryNode().begin(); - new CallInst(m_docFunc, "", &*entry); -#endif // Invoke PrimInfo's static initializer PrimInfo::buildStructType(&m); @@ -233,16 +216,6 @@ for(unsigned i = 0, e = rpairs.size(); i < e; ++i) transformSites(rpairs[i]); -#if 0 - // Dump all documentation from constructed PrimInfo instances into the documentation - // function; we do this here (as opposed to doing it as the objects are constructed) - // to avoid introducing uses of the region function ptrs (which complicates other code - // and isn't as efficient). - - for(vector::iterator i = m_primInfos.begin(), e = m_primInfos.end(); i != e; ++i) - i->Document(m_docFunc); -#endif - // Build the interval PrimInfo instance -> GBT index map. This maps the address of a // particular interval PrimInfo instance to the index in the GBT that corresponds to // the record that represents the start-interval global-volatile and related @@ -341,18 +314,6 @@ else assert(0 && "Use of start call's first opd in non-call inst"); - // {{{ Old implementation -#if 0 - assert(startCall->use_size() == 1 && isa(startCall->use_back()) && "Must see only one use, in a store"); - AllocaInst* ai = dyn_cast(cast(startCall->use_back())->getPointerOperand()); - assert(ai && ai->use_size() == 2 && "Address of stack-local expected as store pointer opd, and has two uses"); - - // CallInst use of stack local one of ai's two uses; it's used once in the store as well - CallInst* endCall = isa(ai->use_back()) ? - cast(ai->use_back()) : dyn_cast(*ai->use_begin()); -#endif - // }}} - assert(startCall->getCalledFunction() == startFunc && endCall->getCalledFunction() == endFunc && "Failed to match start/end call insts with proper functions"); @@ -371,14 +332,6 @@ "Call inst does not have expected format"); return cast(ci->getOperand(1)); - -#if 0 - - assert(ci->use_size() == 1 && isa(ci->use_back()) && "Only use of call return val should be in store"); - StoreInst* si = cast(ci->use_back()); - assert(isa(si->getPointerOperand()) && "Pointer operand of store must be of type global variable"); - return cast(si->getPointerOperand()); -#endif } void Phase1::transformSite(CallInst* startCall, CallInst* endCall) @@ -462,38 +415,6 @@ LoadInst* deref = new LoadInst(newGV, "deref", ci); CastInst* toTmpType = new CastInst(deref, newTmp->getType()->getElementType(), "castToTmpType", ci); new StoreInst(toTmpType, newTmp, ci); - -#if 0 - // Build instructions to store new global volatile into the new temporary; place in - // new BasicBlock containing nothing else. We call this the 'assign' block. - - BasicBlock* gvAssignBlk = new BasicBlock("gvAssignBlk", ci->getParent()->getParent()); - LoadInst* deref = new LoadInst(newGV, "deref"); - gvAssignBlk->getInstList().push_back(deref); - gvAssignBlk->getInstList().push_back(new StoreInst(deref, newTmp)); - - // Build condition wrapper for the load of the global volatile; this is done by - // splitting ci's BasicBlock in two ('before', 'after'), making sure that the before - // block conditionally branches to the assign block or the after block, and that the - // assign block unconditionally branches to the after block. - - BasicBlock* beforeBB = ci->getParent(); - BasicBlock* afterBB = beforeBB->splitBasicBlock(ci->getNext()); - afterBB->setName("ppSplit"); - - // The 'assign' block unconditionally branches to the after block. - gvAssignBlk->getInstList().push_back(new BranchInst(afterBB)); - - // The 'before' block conditionally branches to the assign block and the after block; - // make conditional here as well [if (newTmp > 0) { ... }]. - - BasicBlock::iterator ti(beforeBB->getTerminator()); - LoadInst* li = new LoadInst(newTmp, "tmpDeref", ti); - SetCondInst* sci = new SetCondInst(BinaryOperator::SetGT, li, - Constant::getNullValue(li->getType()), "cond", li->getNext()); - - ReplaceInstWithInst(beforeBB->getInstList(), ti, new BranchInst(gvAssignBlk, afterBB, sci)); -#endif } bool Phase1::run(Module& m) Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp:1.10 llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp:1.11 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp:1.10 Fri May 9 23:02:35 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp Sat May 10 15:54:54 2003 @@ -27,13 +27,6 @@ //////////////// PrimInfo implementation //////////////// StructType* PrimInfo::sm_structType = 0; -CastInst* PrimInfo::sm_dummyCast = 0; - -PrimInfo::PrimInfo(Module& m, CallInst* ci): - m_module(&m) -{ - buildFromCall(ci); -} PrimInfo::PrimInfo(PrimType type, GlobalVariable* startGlob, @@ -95,7 +88,6 @@ assert(!init && "Expect only one invocation of this function"); init = true; - std::vector fields; @@ -103,7 +95,7 @@ fields.push_back(PointerType::get(Type::UShortTy)); // unsigned short* loadVar; fields.push_back(Type::UIntTy); // unsigned gbtStartIdx; fields.push_back(Type::UIntTy); // unsigned paramSize; - //fields.push_back(PointerType::get(Type::VoidTy)); // void* instFunc; + fields.push_back(PointerType::get(Type::VoidTy)); // void* instFunc; sm_structType = StructType::get(fields); module->addTypeName("PrimInfo", sm_structType); @@ -121,7 +113,8 @@ initFlds.push_back(ConstantPointerRef::get(loadVar)); initFlds.push_back(ConstantUInt::get(Type::UIntTy, startLinkIdx)); initFlds.push_back(ConstantUInt::get(Type::UIntTy, paramSize)); - //initFlds.push_back(ConstantPointerRef::get(instFunc)); + initFlds.push_back(ConstantExpr::getCast(ConstantPointerRef::get(instFunc), + PointerType::get(Type::VoidTy))); return ConstantStruct::get(st, initFlds); } @@ -157,125 +150,6 @@ default: assert(0 && "(BuildStructInstances) Unsupported PrimInfo type"); } -} - -void PrimInfo::document(Function* docFunc) -{ - GlobalVariable* gstruct; - - // Build data structure to track configuration about this particular primitive - std::vector initializerFields; - - switch(m_type) { - case COUNTER: - // counter primitives don't use anything but the type field - initializerFields.push_back(ConstantUInt::get(Type::UIntTy, COUNTER)); - initializerFields.push_back(Constant::getNullValue(Type::UIntTy)); - break; - case POINT: - initializerFields.push_back(ConstantUInt::get(Type::UIntTy, POINT)); - initializerFields.push_back(Constant::getNullValue(Type::UIntTy)); - break; - case REGION: - initializerFields.push_back(ConstantUInt::get(Type::UIntTy, REGION)); - initializerFields.push_back(Constant::getNullValue(Type::UIntTy)); - break; - default: - assert(0 && "Unknown metric type"); - break; - } - - ConstantStruct* init = ConstantStruct::get(sm_structType, initializerFields); - gstruct = new GlobalVariable(sm_structType, true, - GlobalVariable::ExternalLinkage, init, - "ctrPrimCfgData", m_module); - - // Construct the call to printf (using dummy string), ensuring that the - // (non-string) parameters are layed out as follows: - // - // When we're dealing with a point computation site: - // - // 1st parameter: global static data structure holding configuration information - // 2nd parameter: metric variable itself - // 3rd parameter: global volatile used as placeholder - // 4th parameter: called function for point (not present for COUNTER type) - // - // When we're dealing with a region computation site - // 1st parameter: global static data structure holding configuration information - // 2nd parameter: metric variable itself - // 3rd parameter: global volatile used as placeholder for start of region - // 4th parameter: global volatile used as placeholder for end of region - // 5th parameter: called function for start of region - // 6th parameter: called function for end of region - - // Build the dummy string and cast to sbyte*; insert cast inst in doc func - - if(!sm_dummyCast) { - ConstantArray* dummyStr = ConstantArray::get("floogle!"); - - GlobalVariable* ds = new GlobalVariable(dummyStr->getType(), true, - GlobalVariable::ExternalLinkage, - dummyStr, "dummyStr", m_module); - - sm_dummyCast = new CastInst(ds, PointerType::get(Type::SByteTy), - "sbyte_cast", docFunc->getEntryNode().getTerminator()); - } - - // Build the printf call & insert it at the end of the doc function - std::vector callParams; - callParams.push_back(sm_dummyCast); - callParams.push_back(gstruct); - callParams.push_back(m_metricVar); - callParams.push_back(m_globVol); - - if(m_type == REGION) { - assert(m_startFunc && m_endFunc && "Must have function ptrs for region"); - callParams.push_back(m_globVolEnd); - callParams.push_back(m_startFunc); - callParams.push_back(m_endFunc); - } - else if(m_type == POINT) { - callParams.push_back(m_startFunc); - } - - Function* printfFunc = m_module->getNamedFunction("printf"); - assert(printfFunc && "Couldn't find printf function in module"); - - new CallInst(printfFunc, callParams, - "printfRet", docFunc->getEntryNode().getTerminator()); -} - -void PrimInfo::buildFromCall(CallInst* ci) -{ - // fp, dummy string are first two args - assert(ci->getNumOperands() > 2 && "Require global struct argument"); - GlobalVariable* gstruct = dyn_cast(ci->getOperand(2)); - assert(gstruct && "Expect to obtain global struct for processing"); - - // extract info from global, then fill in appropriate class fields - const std::vector& values = dyn_cast(gstruct->getInitializer())->getValues(); - m_type = (PrimType) cast(values[0].get())->getValue(); - - assert(m_type == COUNTER && ci->getNumOperands() == 5 || - m_type == POINT && ci->getNumOperands() == 6 || - m_type == REGION && ci->getNumOperands() == 8 && - "Expect proper number of significant arguments in printf call"); - - m_metricVar = dyn_cast(ci->getOperand(3)); - m_globVol = dyn_cast(ci->getOperand(4)); - assert(m_metricVar && m_globVol && "Require proper parameter types in printf"); - - if(m_type == REGION) { - m_globVolEnd = dyn_cast(ci->getOperand(5)); - m_startFunc = dyn_cast(ci->getOperand(6)); - m_endFunc = dyn_cast(ci->getOperand(7)); - assert(m_globVolEnd && m_startFunc && m_endFunc && "Require proper parameter types in printf"); - } - else if(m_type == POINT) { - m_startFunc = dyn_cast(ci->getOperand(5)); - } - - // TODO: Write stuff for specFld here when it becomes relevant } }; // end namespace pp Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h:1.8 llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h:1.9 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h:1.8 Fri May 9 23:02:35 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h Sat May 10 15:54:54 2003 @@ -56,8 +56,6 @@ Function* startFunc, Function* endFunc); - PrimInfo(Module& m, CallInst* ci); // Phase 2 (re)construction - GlobalVariable* getGlobVol() { return m_globVol; } const GlobalVariable* getGlobVol() const { return m_globVol; } GlobalVariable* getGlobVolEnd() { return m_globVolEnd; } @@ -74,11 +72,8 @@ std::map& gbtIdxMap, const TargetData* targetData); - void document(Function* docFunc); - void buildFromCall(CallInst* ci); - - static void buildStructType(Module* module); - static StructType* getStructType() { return sm_structType; } + static void buildStructType(Module* module); + static StructType* getStructType() { return sm_structType; } private: @@ -94,7 +89,6 @@ Function* m_endFunc; static StructType* sm_structType; - static CastInst* sm_dummyCast; }; }; // end namespace pp From lattner at cs.uiuc.edu Sat May 10 15:46:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 15:46:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Ptrdist-bc/const.h Message-ID: <200305102045.PAA27241@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Ptrdist-bc: const.h updated: 1.1 -> 1.2 --- Log message: Don't redefine system #defines unless they are not defined already! --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/Ptrdist-bc/const.h diff -u llvm/test/Programs/MultiSource/Ptrdist-bc/const.h:1.1 llvm/test/Programs/MultiSource/Ptrdist-bc/const.h:1.2 --- llvm/test/Programs/MultiSource/Ptrdist-bc/const.h:1.1 Fri Feb 14 13:14:11 2003 +++ llvm/test/Programs/MultiSource/Ptrdist-bc/const.h Sat May 10 15:45:11 2003 @@ -38,6 +38,7 @@ /* Define constants in some reasonable size. The next 4 constants are POSIX constants. */ +#ifndef BC_BASE_MAX #define BC_BASE_MAX INT_MAX #define BC_SCALE_MAX INT_MAX #define BC_STRING_MAX INT_MAX @@ -46,6 +47,7 @@ /* Definitions for arrays. */ #define BC_DIM_MAX 65535 /* this should be NODE_SIZE^NODE_DEPTH-1 */ +#endif #define NODE_SIZE 16 /* Must be a power of 2. */ #define NODE_MASK 0xf /* Must be NODE_SIZE-1. */ From lattner at cs.uiuc.edu Sat May 10 15:50:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 15:50:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/TEST.nightly.Makefile Message-ID: <200305102049.PAA27257@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: TEST.nightly.Makefile updated: 1.5 -> 1.6 --- Log message: Fix race condition in makefile which was causing tests to fail for no reason! --- Diffs of the changes: Index: llvm/test/Programs/TEST.nightly.Makefile diff -u llvm/test/Programs/TEST.nightly.Makefile:1.5 llvm/test/Programs/TEST.nightly.Makefile:1.6 --- llvm/test/Programs/TEST.nightly.Makefile:1.5 Sat May 10 00:36:58 2003 +++ llvm/test/Programs/TEST.nightly.Makefile Sat May 10 15:49:18 2003 @@ -54,7 +54,7 @@ # CBE tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.cbe.report.txt): \ -Output/%.nightly.cbe.report.txt: Output/%.llvm.bc $(LDIS) +Output/%.nightly.cbe.report.txt: Output/%.llvm.bc Output/%.out-cbe $(LDIS) -($(MAKE) TIME_RUN=1 Output/$*.diff-cbe) 2>&1 | head -n 100 > $@ @if test -f Output/$*.diff-cbe; then \ echo "TEST-RESULT-cbe: YES" >> $@;\ @@ -68,7 +68,7 @@ # LLI tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.lli.report.txt): \ -Output/%.nightly.lli.report.txt: Output/%.llvm.bc $(LLI) +Output/%.nightly.lli.report.txt: Output/%.llvm.bc Output/%.out-cbe $(LLI) -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-lli) 2>&1 | head -n 100 > $@ @if test -e Output/$*.diff-lli; then \ echo "TEST-PASS: lli $(RELDIR)/$*" >> $@;\ @@ -85,7 +85,7 @@ # JIT tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.jit.report.txt): \ -Output/%.nightly.jit.report.txt: Output/%.llvm.bc $(LLI) +Output/%.nightly.jit.report.txt: Output/%.llvm.bc Output/%.out-cbe $(LLI) -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-jit) 2>&1 | head -n 100 > $@ @if test -f Output/$*.diff-jit; then \ echo "TEST-PASS: jit $(RELDIR)/$*" >> $@;\ From lattner at cs.uiuc.edu Sat May 10 15:56:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 15:56:01 2003 Subject: [llvm-commits] CVS: llvm/utils/NightlyTestTemplate.html Message-ID: <200305102055.PAA27856@apoc.cs.uiuc.edu> Changes in directory llvm/utils: NightlyTestTemplate.html updated: 1.6 -> 1.7 --- Log message: Update column info --- Diffs of the changes: Index: llvm/utils/NightlyTestTemplate.html diff -u llvm/utils/NightlyTestTemplate.html:1.6 llvm/utils/NightlyTestTemplate.html:1.7 --- llvm/utils/NightlyTestTemplate.html:1.6 Fri Feb 28 14:05:20 2003 +++ llvm/utils/NightlyTestTemplate.html Sat May 10 15:54:55 2003 @@ -126,18 +126,17 @@

    • Bytecode - The size of the bytecode for the program
    • Instrs - The number of LLVM instructions in the compiled bytecode -
    • LLC - Does the program compile with the Sparc Backend? Note +
    • LLC - The time taken compile with the Sparc Backend. Note that this justs tests to see if the backend runs successfully, not if the generated code works. -
    • CBE - Does the program compile with the C Backend? Note - that this justs tests to see if the code generated compiles, not if it - works. +
    • CBE - The time taken to execute the program after compilation + through the C Backend. If the diff fails, this a *.
    • LLI - How long does the program take to execute in - LLI's interpreter (note that this is capped to 30s). + LLI's interpreter (note that this is capped to ~300s).
    • DynInstrs - How many dynamic instructions are executed by the interpreter, if it finishes.
    • JIT - How long does the program take to execute in the - Just In Time compiler (again, capped to 30s). + Just-In-Time compiler.
    • MachCode - The number of bytes of machine code generated by the JIT.
    • CompTime - The amount of time spent in the JIT itself, From lattner at cs.uiuc.edu Sat May 10 16:20:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 16:20:02 2003 Subject: [llvm-commits] CVS: llvm/utils/NightlyTest.pl Message-ID: <200305102119.QAA32429@apoc.cs.uiuc.edu> Changes in directory llvm/utils: NightlyTest.pl updated: 1.9 -> 1.10 --- Log message: Force overwriting the file if it already exists. --- Diffs of the changes: Index: llvm/utils/NightlyTest.pl diff -u llvm/utils/NightlyTest.pl:1.9 llvm/utils/NightlyTest.pl:1.10 --- llvm/utils/NightlyTest.pl:1.9 Fri Feb 28 14:30:20 2003 +++ llvm/utils/NightlyTest.pl Sat May 10 16:19:00 2003 @@ -292,7 +292,7 @@ } # Compress the test output - system "gzip $Prefix-ProgramTest.txt"; + system "gzip -f $Prefix-ProgramTest.txt"; } my ($TestsAdded, $TestsRemoved, $TestsFixed, $TestsBroken) = ("","","",""); From lattner at cs.uiuc.edu Sat May 10 16:23:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 16:23:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/Interpreter/Execution.cpp Interpreter.h Message-ID: <200305102122.QAA01131@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/Interpreter: Execution.cpp updated: 1.88 -> 1.89 Interpreter.h updated: 1.28 -> 1.29 --- Log message: switch main LLI core execution to use an InstVisitor instead of a switch statement --- Diffs of the changes: Index: llvm/tools/lli/Interpreter/Execution.cpp diff -u llvm/tools/lli/Interpreter/Execution.cpp:1.88 llvm/tools/lli/Interpreter/Execution.cpp:1.89 --- llvm/tools/lli/Interpreter/Execution.cpp:1.88 Sat May 10 15:21:16 2003 +++ llvm/tools/lli/Interpreter/Execution.cpp Sat May 10 16:22:39 2003 @@ -486,7 +486,8 @@ return Dest; } -static void executeBinaryInst(BinaryOperator &I, ExecutionContext &SF) { +void Interpreter::visitBinaryOperator(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); const Type *Ty = I.getOperand(0)->getType(); GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); @@ -577,7 +578,8 @@ PerformExitStuff(); } -void Interpreter::executeRetInst(ReturnInst &I, ExecutionContext &SF) { +void Interpreter::visitReturnInst(ReturnInst &I) { + ExecutionContext &SF = ECStack.back(); const Type *RetTy = 0; GenericValue Result; @@ -631,7 +633,8 @@ } } -void Interpreter::executeBrInst(BranchInst &I, ExecutionContext &SF) { +void Interpreter::visitBranchInst(BranchInst &I) { + ExecutionContext &SF = ECStack.back(); BasicBlock *Dest; Dest = I.getSuccessor(0); // Uncond branches have a fixed dest... @@ -643,7 +646,8 @@ SwitchToNewBasicBlock(Dest, SF); } -void Interpreter::executeSwitchInst(SwitchInst &I, ExecutionContext &SF) { +void Interpreter::visitSwitchInst(SwitchInst &I) { + ExecutionContext &SF = ECStack.back(); GenericValue CondVal = getOperandValue(I.getOperand(0), SF); const Type *ElTy = I.getOperand(0)->getType(); @@ -681,6 +685,8 @@ std::vector ResultValues; for (; PHINode *PN = dyn_cast(SF.CurInst); ++SF.CurInst) { + if (Trace) CW << "Run:" << PN; + // Search for the value corresponding to this previous bb... int i = PN->getBasicBlockIndex(PrevBB); assert(i != -1 && "PHINode doesn't contain entry for predecessor??"); @@ -702,7 +708,9 @@ // Memory Instruction Implementations //===----------------------------------------------------------------------===// -void Interpreter::executeAllocInst(AllocationInst &I, ExecutionContext &SF) { +void Interpreter::visitAllocationInst(AllocationInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getType()->getElementType(); // Type to be allocated // Get the number of elements being allocated by the array... @@ -720,7 +728,8 @@ ECStack.back().Allocas.add(Memory); } -static void executeFreeInst(FreeInst &I, ExecutionContext &SF) { +void Interpreter::visitFreeInst(FreeInst &I) { + ExecutionContext &SF = ECStack.back(); assert(isa(I.getOperand(0)->getType()) && "Freeing nonptr?"); GenericValue Value = getOperandValue(I.getOperand(0), SF); // TODO: Check to make sure memory is allocated @@ -784,19 +793,22 @@ return Result; } -static void executeGEPInst(GetElementPtrInst &I, ExecutionContext &SF) { +void Interpreter::visitGetElementPtrInst(GetElementPtrInst &I) { + ExecutionContext &SF = ECStack.back(); SetValue(&I, TheEE->executeGEPOperation(I.getPointerOperand(), I.idx_begin(), I.idx_end(), SF), SF); } -void Interpreter::executeLoadInst(LoadInst &I, ExecutionContext &SF) { +void Interpreter::visitLoadInst(LoadInst &I) { + ExecutionContext &SF = ECStack.back(); GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); GenericValue *Ptr = (GenericValue*)GVTOP(SRC); GenericValue Result = LoadValueFromMemory(Ptr, I.getType()); SetValue(&I, Result, SF); } -void Interpreter::executeStoreInst(StoreInst &I, ExecutionContext &SF) { +void Interpreter::visitStoreInst(StoreInst &I) { + ExecutionContext &SF = ECStack.back(); GenericValue Val = getOperandValue(I.getOperand(0), SF); GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); StoreValueToMemory(Val, (GenericValue *)GVTOP(SRC), @@ -809,8 +821,9 @@ // Miscellaneous Instruction Implementations //===----------------------------------------------------------------------===// -void Interpreter::executeCallInst(CallInst &I, ExecutionContext &SF) { - ECStack.back().Caller = &I; +void Interpreter::visitCallInst(CallInst &I) { + ExecutionContext &SF = ECStack.back(); + SF.Caller = &I; std::vector ArgVals; ArgVals.reserve(I.getNumOperands()-1); for (unsigned i = 1; i < I.getNumOperands(); ++i) { @@ -838,15 +851,15 @@ // To handle indirect calls, we must get the pointer value from the argument // and treat it as a function pointer. - GenericValue SRC = getOperandValue(I.getCalledValue(), SF); - + GenericValue SRC = getOperandValue(I.getCalledValue(), SF); callFunction((Function*)GVTOP(SRC), ArgVals); } #define IMPLEMENT_SHIFT(OP, TY) \ case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.UByteVal; break -static void executeShlInst(ShiftInst &I, ExecutionContext &SF) { +void Interpreter::visitShl(ShiftInst &I) { + ExecutionContext &SF = ECStack.back(); const Type *Ty = I.getOperand(0)->getType(); GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); @@ -867,7 +880,8 @@ SetValue(&I, Dest, SF); } -static void executeShrInst(ShiftInst &I, ExecutionContext &SF) { +void Interpreter::visitShr(ShiftInst &I) { + ExecutionContext &SF = ECStack.back(); const Type *Ty = I.getOperand(0)->getType(); GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); @@ -948,11 +962,14 @@ } -static void executeCastInst(CastInst &I, ExecutionContext &SF) { +void Interpreter::visitCastInst(CastInst &I) { + ExecutionContext &SF = ECStack.back(); SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF); } -static void executeVarArgInst(VarArgInst &I, ExecutionContext &SF) { +void Interpreter::visitVarArgInst(VarArgInst &I) { + ExecutionContext &SF = ECStack.back(); + // Get the pointer to the valist element. LLI treats the valist in memory as // an integer. GenericValue VAListPtr = getOperandValue(I.getOperand(0), SF); @@ -1081,8 +1098,7 @@ ExecutionContext &SF = ECStack.back(); // Current stack frame Instruction &I = *SF.CurInst++; // Increment before execute - if (Trace) - CW << "Run:" << I; + if (Trace) CW << "Run:" << I; // Track the number of dynamic instructions executed. ++NumDynamicInsts; @@ -1107,37 +1123,7 @@ } InInstruction = true; - if (I.isBinaryOp()) { - executeBinaryInst(cast(I), SF); - } else { - switch (I.getOpcode()) { - // Terminators - case Instruction::Ret: executeRetInst (cast(I), SF); break; - case Instruction::Br: executeBrInst (cast(I), SF); break; - case Instruction::Switch: executeSwitchInst(cast(I), SF);break; - // Invoke not handled! - - // Memory Instructions - case Instruction::Alloca: - case Instruction::Malloc: executeAllocInst((AllocationInst&)I, SF); break; - case Instruction::Free: executeFreeInst (cast (I), SF); break; - case Instruction::Load: executeLoadInst (cast (I), SF); break; - case Instruction::Store: executeStoreInst(cast(I), SF); break; - case Instruction::GetElementPtr: - executeGEPInst(cast(I), SF); break; - - // Miscellaneous Instructions - case Instruction::Call: executeCallInst (cast (I), SF); break; - case Instruction::PHINode: assert(0 && "PHI nodes already handled!"); - case Instruction::Cast: executeCastInst (cast (I), SF); break; - case Instruction::Shl: executeShlInst (cast(I), SF); break; - case Instruction::Shr: executeShrInst (cast(I), SF); break; - case Instruction::VarArg: executeVarArgInst(cast(I),SF); break; - default: - std::cout << "Don't know how to execute this instruction!\n-->" << I; - abort(); - } - } + visit(I); // Dispatch to one of the visit* methods... InInstruction = false; // Reset the current frame location to the top of stack Index: llvm/tools/lli/Interpreter/Interpreter.h diff -u llvm/tools/lli/Interpreter/Interpreter.h:1.28 llvm/tools/lli/Interpreter/Interpreter.h:1.29 --- llvm/tools/lli/Interpreter/Interpreter.h:1.28 Sat May 10 15:21:16 2003 +++ llvm/tools/lli/Interpreter/Interpreter.h Sat May 10 16:22:39 2003 @@ -11,22 +11,16 @@ //#define PROFILE_STRUCTURE_FIELDS 1 #include "../ExecutionEngine.h" +#include "../GenericValue.h" #include "Support/DataTypes.h" #include "llvm/Assembly/CachedWriter.h" #include "llvm/Target/TargetData.h" #include "llvm/BasicBlock.h" -#include "../GenericValue.h" +#include "llvm/Support/InstVisitor.h" extern CachedWriter CW; // Object to accelerate printing of LLVM struct FunctionInfo; // Defined in ExecutionAnnotations.h -class CallInst; -class ReturnInst; -class BranchInst; -class SwitchInst; -class LoadInst; -class StoreInst; -class AllocationInst; // AllocaHolder - Object to track all of the blocks of memory allocated by // alloca. When the function returns, this object is poped off the execution @@ -78,7 +72,7 @@ // Interpreter - This class represents the entirety of the interpreter. // -class Interpreter : public ExecutionEngine { +class Interpreter : public ExecutionEngine, public InstVisitor { int ExitCode; // The exit code to be returned by the lli util bool Debug; // Debug mode enabled? bool Profile; // Profiling enabled? @@ -134,11 +128,28 @@ void finish(); // Do the 'finish' command // Opcode Implementations - void executeCallInst(CallInst &I, ExecutionContext &SF); - void executeRetInst(ReturnInst &I, ExecutionContext &SF); - void executeBrInst(BranchInst &I, ExecutionContext &SF); - void executeSwitchInst(SwitchInst &I, ExecutionContext &SF); - void executeAllocInst(AllocationInst &I, ExecutionContext &SF); + void visitReturnInst(ReturnInst &I); + void visitBranchInst(BranchInst &I); + void visitSwitchInst(SwitchInst &I); + + void visitBinaryOperator(BinaryOperator &I); + void visitAllocationInst(AllocationInst &I); + void visitFreeInst(FreeInst &I); + void visitLoadInst(LoadInst &I); + void visitStoreInst(StoreInst &I); + void visitGetElementPtrInst(GetElementPtrInst &I); + + void visitPHINode(PHINode &PN) { assert(0 && "PHI nodes already handled!"); } + void visitCastInst(CastInst &I); + void visitCallInst(CallInst &I); + void visitShl(ShiftInst &I); + void visitShr(ShiftInst &I); + void visitVarArgInst(VarArgInst &I); + void visitInstruction(Instruction &I) { + std::cerr << I; + assert(0 && "Instruction not interpretable yet!"); + } + GenericValue callExternalFunction(Function *F, const std::vector &ArgVals); void exitCalled(GenericValue GV); @@ -157,9 +168,6 @@ public: GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I, User::op_iterator E, ExecutionContext &SF); - void executeLoadInst(LoadInst &I, ExecutionContext &SF); - void executeStoreInst(StoreInst &I, ExecutionContext &SF); - private: // Helper functions // SwitchToNewBasicBlock - Start execution in a new basic block and run any From lattner at cs.uiuc.edu Sat May 10 16:38:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 16:38:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile.programs Message-ID: <200305102137.QAA03761@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile.programs updated: 1.41 -> 1.42 --- Log message: Fix build breakage with nightly tester --- Diffs of the changes: Index: llvm/test/Programs/Makefile.programs diff -u llvm/test/Programs/Makefile.programs:1.41 llvm/test/Programs/Makefile.programs:1.42 --- llvm/test/Programs/Makefile.programs:1.41 Sat May 10 15:40:20 2003 +++ llvm/test/Programs/Makefile.programs Sat May 10 16:37:33 2003 @@ -184,9 +184,11 @@ # # Rules to compile the program for the C Back End # +$(PROGRAMS_TO_TEST:%=Output/%.cbe.c): \ Output/%.cbe.c: Output/%.llvm.bc $(LDIS) $(LDIS) -c < $< > $@ +$(PROGRAMS_TO_TEST:%=Output/%.cbe): \ Output/%.cbe: Output/%.cbe.c $(CC) -o $@ $< $(LDFLAGS) $(CFLAGS) From lattner at cs.uiuc.edu Sat May 10 16:41:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat May 10 16:41:01 2003 Subject: [llvm-commits] CVS: llvm/utils/NightlyTest.pl Message-ID: <200305102140.QAA03785@apoc.cs.uiuc.edu> Changes in directory llvm/utils: NightlyTest.pl updated: 1.10 -> 1.11 --- Log message: Get the nightly tester to detect other kind of testing problems --- Diffs of the changes: Index: llvm/utils/NightlyTest.pl diff -u llvm/utils/NightlyTest.pl:1.10 llvm/utils/NightlyTest.pl:1.11 --- llvm/utils/NightlyTest.pl:1.10 Sat May 10 16:19:00 2003 +++ llvm/utils/NightlyTest.pl Sat May 10 16:40:10 2003 @@ -279,8 +279,8 @@ if (`grep '^gmake: .*Error' $Prefix-ProgramTest.txt | wc -l` + 0) { $TestError = 1; - $ProgramsTable = "

      Error running tests!

      "; - } else { + $ProgramsTable = "

      Error running tests!

      "; + } elsif (`grep '^gmake: .*No rule to make target' $Prefix-ProgramTest.txt | wc -l` + 0) { $TestError = 0; $ProgramsTable = ReadFile "report.nightly.html"; From lattner at cs.uiuc.edu Sun May 11 10:24:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 10:24:01 2003 Subject: [llvm-commits] CVS: llvm/utils/NightlyTest.pl Message-ID: <200305111523.KAA02738@apoc.cs.uiuc.edu> Changes in directory llvm/utils: NightlyTest.pl updated: 1.11 -> 1.12 --- Log message: Fix a halfway done change to the nightly tester :( --- Diffs of the changes: Index: llvm/utils/NightlyTest.pl diff -u llvm/utils/NightlyTest.pl:1.11 llvm/utils/NightlyTest.pl:1.12 --- llvm/utils/NightlyTest.pl:1.11 Sat May 10 16:40:10 2003 +++ llvm/utils/NightlyTest.pl Sun May 11 10:23:10 2003 @@ -281,6 +281,10 @@ $TestError = 1; $ProgramsTable = "

      Error running tests!

      "; } elsif (`grep '^gmake: .*No rule to make target' $Prefix-ProgramTest.txt | wc -l` + 0) { + $TestError = 1; + $ProgramsTable = + "

      Makefile error running tests!

      "; + } else { $TestError = 0; $ProgramsTable = ReadFile "report.nightly.html"; From lattner at cs.uiuc.edu Sun May 11 12:35:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 12:35:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/RunSafely.sh Message-ID: <200305111734.MAA17585@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: RunSafely.sh updated: 1.1 -> 1.2 --- Log message: Capture timing information and stdout/stderr to a file --- Diffs of the changes: Index: llvm/test/Programs/RunSafely.sh diff -u llvm/test/Programs/RunSafely.sh:1.1 llvm/test/Programs/RunSafely.sh:1.2 --- llvm/test/Programs/RunSafely.sh:1.1 Sun Jan 19 12:07:38 2003 +++ llvm/test/Programs/RunSafely.sh Sun May 11 12:34:14 2003 @@ -7,15 +7,20 @@ # like print a stack trace of a core dump. It always returns # "successful" so that tests will continue to be run. # -# Syntax: ./RunSafely.sh +# This script funnels stdout and stderr from the program into the +# first argument specified, and outputs a .time file which +# contains a timing of the program. # - +# Syntax: ./RunSafely.sh +# +OUTFILE=$1 +shift PROGRAM=$1 shift -rm -f core* +rm -f core core.* ulimit -c hard -$PROGRAM $* +(time -p $PROGRAM $* > $OUTFILE 2>&1) 2> $OUTFILE.time if ls | egrep "^core" > /dev/null then corefile=`ls core* | head -1` From lattner at cs.uiuc.edu Sun May 11 12:35:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 12:35:06 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile.programs TEST.nightly.Makefile Message-ID: <200305111734.MAA17601@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile.programs updated: 1.42 -> 1.43 TEST.nightly.Makefile updated: 1.6 -> 1.7 --- Log message: Make the testing results more reliable, working around an apparent make bug --- Diffs of the changes: Index: llvm/test/Programs/Makefile.programs diff -u llvm/test/Programs/Makefile.programs:1.42 llvm/test/Programs/Makefile.programs:1.43 --- llvm/test/Programs/Makefile.programs:1.42 Sat May 10 16:37:33 2003 +++ llvm/test/Programs/Makefile.programs Sun May 11 12:34:39 2003 @@ -68,7 +68,7 @@ # stack trace of a core dump. It always returns "successful" so that tests will # continue to be run. ULIMIT := ulimit -t $(RUNTIMELIMIT) -RUNSAFELY := $(PROGDIR)/RunSafely.sh +RUNSAFELY := $(ULIMIT); $(PROGDIR)/RunSafely.sh # # Targets to build for the default target... @@ -205,32 +205,31 @@ ifndef USE_PRECOMPILED_BYTECODE $(PROGRAMS_TO_TEST:%=Output/%.out-nat): \ Output/%.out-nat: Output/%.native - -$(ULIMIT); $(RUNSAFELY) $< > $@ $(RUN_OPTIONS) + -$(RUNSAFELY) $@ $< $(RUN_OPTIONS) endif # EXTRA_LLI_OPTS is used by the nightly tester to add arguments to invocations # of the JIT and LLI in order to get timing info and statistics. EXTRA_LLI_OPTS := -LLI_OPTS := -q -abort-on-exception -force-interpreter=true $(EXTRA_LLI_OPTS) -JIT_OPTS := -force-interpreter=false $(EXTRA_LLI_OPTS) - -ifdef TIME_RUN -TIME := time -p -endif +LLI_OPTS = -q -abort-on-exception -force-interpreter=true $(EXTRA_LLI_OPTS) +JIT_OPTS = -force-interpreter=false $(EXTRA_LLI_OPTS) $(PROGRAMS_TO_TEST:%=Output/%.out-lli): \ Output/%.out-lli: Output/%.llvm.bc $(LLI) - -$(ULIMIT); $(TIME) $(RUNSAFELY) $(LLI) $(LLI_OPTS) $< > $@ $(RUN_OPTIONS) + -$(RUNSAFELY) $@ $(LLI) $(LLI_OPTS) $< $(RUN_OPTIONS) + $(PROGRAMS_TO_TEST:%=Output/%.out-jit): \ Output/%.out-jit: Output/%.llvm.bc $(LLI) - -$(ULIMIT); $(TIME) $(RUNSAFELY) $(LLI) $(JIT_OPTS) $< > $@ $(RUN_OPTIONS) + -$(RUNSAFELY) $@ $(LLI) $(JIT_OPTS) $< $(RUN_OPTIONS) + $(PROGRAMS_TO_TEST:%=Output/%.out-llc): \ Output/%.out-llc: Output/%.llc - -$(ULIMIT); $(TIME) $(RUNSAFELY) $< > $@ $(RUN_OPTIONS) + -$(RUNSAFELY) $@ $< $(RUN_OPTIONS) + $(PROGRAMS_TO_TEST:%=Output/%.out-cbe): \ Output/%.out-cbe: Output/%.cbe - -$(ULIMIT); $(TIME) $(RUNSAFELY) $< > $@ $(RUN_OPTIONS) + -$(RUNSAFELY) $@ $< $(RUN_OPTIONS) # # Rules to diff test output... Index: llvm/test/Programs/TEST.nightly.Makefile diff -u llvm/test/Programs/TEST.nightly.Makefile:1.6 llvm/test/Programs/TEST.nightly.Makefile:1.7 --- llvm/test/Programs/TEST.nightly.Makefile:1.6 Sat May 10 15:49:18 2003 +++ llvm/test/Programs/TEST.nightly.Makefile Sun May 11 12:34:39 2003 @@ -13,6 +13,7 @@ REPORTS_SUFFIX := $(addsuffix .report.txt, $(REPORTS_TO_GEN)) TIMEOPT = -time-passes -stats -info-output-file=$@.info +EXTRA_LLI_OPTS = $(TIMEOPT) # Compilation tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.compile.report.txt): \ @@ -54,54 +55,51 @@ # CBE tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.cbe.report.txt): \ -Output/%.nightly.cbe.report.txt: Output/%.llvm.bc Output/%.out-cbe $(LDIS) - -($(MAKE) TIME_RUN=1 Output/$*.diff-cbe) 2>&1 | head -n 100 > $@ +Output/%.nightly.cbe.report.txt: Output/%.llvm.bc Output/%.diff-cbe $(LDIS) + -head -n 100 Output/$*.diff-cbe > $@ @if test -f Output/$*.diff-cbe; then \ echo "TEST-RESULT-cbe: YES" >> $@;\ echo -n "TEST-RESULT-cbe-time: " >> $@;\ - grep "^real" $@ >> $@;\ + grep "^real" Output/$*.out-cbe.time >> $@;\ echo >> $@;\ else \ echo "TEST-FAIL: cbe $(RELDIR)/$*" >> $@;\ fi - # LLI tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.lli.report.txt): \ -Output/%.nightly.lli.report.txt: Output/%.llvm.bc Output/%.out-cbe $(LLI) - -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-lli) 2>&1 | head -n 100 > $@ +Output/%.nightly.lli.report.txt: Output/%.llvm.bc Output/%.diff-lli $(LLI) + -head -n 100 Output/$*.diff-lli > $@ @if test -e Output/$*.diff-lli; then \ echo "TEST-PASS: lli $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-lli-time: " >> $@;\ - grep "^real" $@ >> $@;\ + grep "^real" Output/$*.out-jit.time >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-lli-dyninst: " >> $@;\ - grep "Number of dynamic inst" $@.info >> $@;\ + grep "Number of dynamic inst" Output/$*.out-lli.info >> $@;\ echo >> $@;\ else \ echo "TEST-FAIL: lli $(RELDIR)/$*" >> $@;\ fi - - at rm -f $@.info # JIT tests $(PROGRAMS_TO_TEST:%=Output/%.nightly.jit.report.txt): \ -Output/%.nightly.jit.report.txt: Output/%.llvm.bc Output/%.out-cbe $(LLI) - -($(MAKE) EXTRA_LLI_OPTS='$(TIMEOPT)' TIME_RUN=1 Output/$*.diff-jit) 2>&1 | head -n 100 > $@ +Output/%.nightly.jit.report.txt: Output/%.llvm.bc Output/%.diff-jit $(LLI) + -head -n 100 Output/$*.diff-jit > $@ @if test -f Output/$*.diff-jit; then \ echo "TEST-PASS: jit $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-jit-time: " >> $@;\ - grep "^real" $@ >> $@;\ + grep "^real" Output/$*.out-jit.time >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-jit-comptime: " >> $@;\ - grep "Total Execution Time" $@.info >> $@;\ + grep "Total Execution Time" Output/$*.out-jit.info >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-jit-machcode: " >> $@;\ - grep "bytes of machine code compiled" $@.info >> $@;\ + grep "bytes of machine code compiled" Output/$*.out-jit.info >> $@;\ echo >> $@;\ else \ echo "TEST-FAIL: jit $(RELDIR)/$*" >> $@;\ fi - - at rm -f $@.info # Overall tests: just run subordinate tests $(PROGRAMS_TO_TEST:%=Output/%.$(TEST).report.txt): \ From lattner at cs.uiuc.edu Sun May 11 13:26:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 13:26:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/TEST.nightly.Makefile Message-ID: <200305111825.NAA26876@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: TEST.nightly.Makefile updated: 1.7 -> 1.8 --- Log message: Fix copy-and-pasteo --- Diffs of the changes: Index: llvm/test/Programs/TEST.nightly.Makefile diff -u llvm/test/Programs/TEST.nightly.Makefile:1.7 llvm/test/Programs/TEST.nightly.Makefile:1.8 --- llvm/test/Programs/TEST.nightly.Makefile:1.7 Sun May 11 12:34:39 2003 +++ llvm/test/Programs/TEST.nightly.Makefile Sun May 11 13:25:40 2003 @@ -73,7 +73,7 @@ @if test -e Output/$*.diff-lli; then \ echo "TEST-PASS: lli $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-lli-time: " >> $@;\ - grep "^real" Output/$*.out-jit.time >> $@;\ + grep "^real" Output/$*.out-lli.time >> $@;\ echo >> $@;\ echo -n "TEST-RESULT-lli-dyninst: " >> $@;\ grep "Number of dynamic inst" Output/$*.out-lli.info >> $@;\ From lattner at cs.uiuc.edu Sun May 11 13:39:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 13:39:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/LLC/Makefile Message-ID: <200305111838.NAA30263@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/LLC: Makefile updated: 1.5 -> 1.6 --- Log message: Allow llx tests as well --- Diffs of the changes: Index: llvm/test/Regression/LLC/Makefile diff -u llvm/test/Regression/LLC/Makefile:1.5 llvm/test/Regression/LLC/Makefile:1.6 --- llvm/test/Regression/LLC/Makefile:1.5 Thu Jan 23 10:51:24 2003 +++ llvm/test/Regression/LLC/Makefile Sun May 11 13:38:25 2003 @@ -7,11 +7,16 @@ # Only .ll tests here. C tests are run via Makefile.singlesrc above. # -TESTS := $(wildcard *.ll) +LL_TESTS := $(wildcard *.ll) +LLX_TESTS := $(wildcard *.llx) -all:: $(addprefix Output/, $(filter-out %.c, $(TESTS:%.ll=%.ts))) +all:: $(addprefix Output/, $(LL_TESTS:%.ll=%.ts)) +all:: $(addprefix Output/, $(LLX_TESTS:%.llx=%.llx.out)) Output/%.ts: Output/%.bc $(LLC) Output/.dir @echo "======== Compiling $< ==========" $(LLC) -f $< -o $@ || \ ( rm -f $@; $(FAILURE) $@ ) + +Output/%.llx.out: %.llx Output/.dir $(LLC) + -$(TESTRUNR) $< From lattner at cs.uiuc.edu Sun May 11 13:50:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 13:50:01 2003 Subject: [llvm-commits] CVS: llvm/test/Makefile.tests Message-ID: <200305111849.NAA10448@morpheus.cs.uiuc.edu> Changes in directory llvm/test: Makefile.tests updated: 1.54 -> 1.55 --- Log message: * Remove dead hunk of makefile fragment for dealing with sun compiler * Move LLC code gen stuff into test/Programs/Makefile.programs --- Diffs of the changes: Index: llvm/test/Makefile.tests diff -u llvm/test/Makefile.tests:1.54 llvm/test/Makefile.tests:1.55 --- llvm/test/Makefile.tests:1.54 Thu May 8 23:19:58 2003 +++ llvm/test/Makefile.tests Sun May 11 13:49:10 2003 @@ -67,14 +67,6 @@ NATGCC = /usr/dcs/software/supported/bin/gcc CP = /bin/cp -f -ifndef DISABLE_LLC_DIFFS -CC = /opt/SUNWspro/bin/cc -AS = /opt/SUNWspro/bin/cc -DIS = /usr/ccs/bin/dis -CFLAGS += -g -xarch=v9 -endif - - ifeq ($(TRACE), yes) LLCFLAGS += -trace basicblock LLCLIBS := -L$(LEVEL)/test/Libraries/Output -linstr64 @@ -106,16 +98,6 @@ # Output/%.bc: %.ll $(LAS) Output/.dir $(LAS) -f $< -o $@ - -# Compile a linked program to machine code for this processor. -# -Output/%.llc.s: Output/%.llvm.bc $(LLC) - $(LLC) $(LLCFLAGS) -f $< -o $@ - -# Assemble (and link) an LLVM-linked program using the system assembler... -# -Output/%.llc: Output/%.llc.s - $(CC) $(CFLAGS) $< $(LLCLIBS) -o $@ # # Testing versions of provided utilities... From lattner at cs.uiuc.edu Sun May 11 13:50:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 13:50:06 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile.programs Message-ID: <200305111849.NAA10461@morpheus.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile.programs updated: 1.43 -> 1.44 --- Log message: * Don't stop the build if something fails * Move llc code gen stuff from Makefile.tests --- Diffs of the changes: Index: llvm/test/Programs/Makefile.programs diff -u llvm/test/Programs/Makefile.programs:1.43 llvm/test/Programs/Makefile.programs:1.44 --- llvm/test/Programs/Makefile.programs:1.43 Sun May 11 12:34:39 2003 +++ llvm/test/Programs/Makefile.programs Sun May 11 13:49:34 2003 @@ -186,11 +186,25 @@ # $(PROGRAMS_TO_TEST:%=Output/%.cbe.c): \ Output/%.cbe.c: Output/%.llvm.bc $(LDIS) - $(LDIS) -c < $< > $@ + -$(LDIS) -c < $< > $@ $(PROGRAMS_TO_TEST:%=Output/%.cbe): \ Output/%.cbe: Output/%.cbe.c - $(CC) -o $@ $< $(LDFLAGS) $(CFLAGS) + -$(CC) -o $@ $< $(LDFLAGS) $(CFLAGS) + +# +# Compile a linked program to machine code with LLC. +# +$(PROGRAMS_TO_TEST:%=Output/%.llc.s): \ +Output/%.llc.s: Output/%.llvm.bc $(LLC) + -$(LLC) $(LLCFLAGS) -f $< -o $@ + +# Assemble (and link) an LLVM-linked program using the system assembler... +# +$(PROGRAMS_TO_TEST:%=Output/%.llc): \ +Output/%.llc: Output/%.llc.s + -$(CC) $(CFLAGS) $< $(LLCLIBS) -o $@ + # # Rules to execute the program From lattner at cs.uiuc.edu Sun May 11 13:56:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 13:56:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/RunSafely.sh Message-ID: <200305111855.NAA31056@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: RunSafely.sh updated: 1.2 -> 1.3 --- Log message: Changes to make it compatible with Sun systems --- Diffs of the changes: Index: llvm/test/Programs/RunSafely.sh diff -u llvm/test/Programs/RunSafely.sh:1.2 llvm/test/Programs/RunSafely.sh:1.3 --- llvm/test/Programs/RunSafely.sh:1.2 Sun May 11 12:34:14 2003 +++ llvm/test/Programs/RunSafely.sh Sun May 11 13:55:29 2003 @@ -19,8 +19,8 @@ shift rm -f core core.* -ulimit -c hard -(time -p $PROGRAM $* > $OUTFILE 2>&1) 2> $OUTFILE.time +ulimit -c unlimited +(time -p $PROGRAM $* > $OUTFILE) 2> $OUTFILE.time if ls | egrep "^core" > /dev/null then corefile=`ls core* | head -1` From lattner at cs.uiuc.edu Sun May 11 14:14:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 14:14:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/DiffOutput.sh Message-ID: <200305111913.OAA14098@morpheus.cs.uiuc.edu> Changes in directory llvm/test/Programs: DiffOutput.sh updated: 1.6 -> 1.7 --- Log message: Do not print out thousands of lines of useless output. --- Diffs of the changes: Index: llvm/test/Programs/DiffOutput.sh diff -u llvm/test/Programs/DiffOutput.sh:1.6 llvm/test/Programs/DiffOutput.sh:1.7 --- llvm/test/Programs/DiffOutput.sh:1.6 Sat May 10 15:27:26 2003 +++ llvm/test/Programs/DiffOutput.sh Sun May 11 14:13:38 2003 @@ -24,7 +24,7 @@ # They are different! echo "******************** TEST '$2' FAILED! ********************" echo "Execution Context Diff:" - cat $DIFFOUTPUT + head -n 200 $DIFFOUTPUT rm $DIFFOUTPUT echo "******************** TEST '$2' FAILED! ********************" ) From lattner at cs.uiuc.edu Sun May 11 15:17:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 15:17:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/Shootout/strcat.c Message-ID: <200305112016.PAA21427@morpheus.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource/Shootout: strcat.c added (r1.1) --- Log message: Simple test --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/Shootout/strcat.c diff -c /dev/null llvm/test/Programs/SingleSource/Shootout/strcat.c:1.1 *** /dev/null Sun May 11 15:16:56 2003 --- llvm/test/Programs/SingleSource/Shootout/strcat.c Sun May 11 15:16:45 2003 *************** *** 0 **** --- 1,36 ---- + /* -*- mode: c -*- + * $Id: strcat.c,v 1.1 2003/05/11 20:16:45 lattner Exp $ + * http://www.bagley.org/~doug/shootout/ + */ + + #include + #include + #include + + #define STUFF "hello\n" + + int + main(int argc, char *argv[]) { + int n = ((argc == 2) ? atoi(argv[1]) : 1); + int i, buflen = 32; + char *strbuf = calloc(sizeof(char), buflen); + char *strend = strbuf; + int stufflen = strlen(STUFF); + + if (!strbuf) { perror("calloc strbuf"); exit(1); } + for (i=0; i Changes in directory llvm/www/pubs: 2003-04-29-DataStructureAnalysisTR.html added (r1.1) --- Log message: Initial checkin --- Diffs of the changes: Index: llvm/www/pubs/2003-04-29-DataStructureAnalysisTR.html diff -c /dev/null llvm/www/pubs/2003-04-29-DataStructureAnalysisTR.html:1.1 *** /dev/null Sun May 11 16:35:35 2003 --- llvm/www/pubs/2003-04-29-DataStructureAnalysisTR.html Sun May 11 16:35:25 2003 *************** *** 0 **** --- 1,63 ---- + + + + Data Structure Analysis: An Efficient Context-Sensitive Heap Analysis + + + +


      + + + Data Structure Analysis:
      An Efficient Context-Sensitive Heap Analysis +

      + + +
      Chris Lattner and + Vikram Adve +

      + + +

      Abstract:

      +
      + This paper presents an efficient context-sensitive heap analysis algorithm + called Data Structure Analysis designed to enable analyses and transformations + on entire disjoint recursive data structures. The analysis has several + challenging properties needed to enable such transformations: + context-sensitivity with cloning (essential for proving disjointness), + field-sensitivity, and the use of an explicit heap model rather + than just alias information. It is also applicable to arbitrary C programs. To + our knowledge no prior work provides all these properties and is + efficient and scalable enough for large programs. Measurements for 29 programs + show that the algorithm is extremely fast, space-efficient, and scales almost + linearly across 3 orders-of-magnitude of code size. + +
      + +

      Published:

      +
        + "Data Structure Analysis: An Efficient Context-Sensitive Heap Analysis", + Chris Lattner & Vikram Adve
        + Technical Report #UIUCDCS-R-2003-2340, Computer Science Dept., Univ. of Illinois, Apr. 2003. +
      + +

      Download:

      + + +

      Bibtex Entry:

      +
      +   @TechReport{LattnerAdve:DSA,
      +     Author      = {Chris Lattner and Vikram Adve},
      +     Title       = {Data Structure Analysis: An Efficient Context-Sensitive Heap Analysis},
      +     Institution = {Computer Science Dept.,
      +                    Univ. of Illinois at Urbana-Champaign},
      +     Number      = {UIUCDCS-R-2003-2340},
      +     Type        = {Tech. Report},
      +     Month       = {Apr},
      +     Year        = {2003}
      +   }
      + 
      + + From lattner at cs.uiuc.edu Sun May 11 16:37:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 16:37:01 2003 Subject: [llvm-commits] CVS: llvm/www/www-index.html Message-ID: <200305112136.QAA01512@tank.cs.uiuc.edu> Changes in directory llvm/www: www-index.html updated: 1.31 -> 1.32 --- Log message: Add link to web page, not directly to PDF file --- Diffs of the changes: Index: llvm/www/www-index.html diff -u llvm/www/www-index.html:1.31 llvm/www/www-index.html:1.32 --- llvm/www/www-index.html:1.31 Fri May 9 13:24:44 2003 +++ llvm/www/www-index.html Sun May 11 16:36:21 2003 @@ -107,8 +107,7 @@ Annual GCC Developers' Summit, Ottawa, Canada, May 2003.
    • -
    • "Data +
    • "Data Structure Analysis: An Efficient Context-Sensitive Heap Analysis"
      Chris Lattner & Vikram Adve, Technical From lattner at cs.uiuc.edu Sun May 11 16:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 16:42:01 2003 Subject: [llvm-commits] CVS: llvm/Makefile.SunOS Message-ID: <200305112141.QAA04811@morpheus.cs.uiuc.edu> Changes in directory llvm: Makefile.SunOS updated: 1.7 -> 1.8 --- Log message: Switch over to using the New CFE on Sparc --- Diffs of the changes: Index: llvm/Makefile.SunOS diff -u llvm/Makefile.SunOS:1.7 llvm/Makefile.SunOS:1.8 --- llvm/Makefile.SunOS:1.7 Fri Jan 31 13:00:26 2003 +++ llvm/Makefile.SunOS Sun May 11 16:41:09 2003 @@ -28,5 +28,6 @@ # be overriden by the Makefile.config option, and should not override it if set. # ifndef LLVMGCCDIR -LLVMGCCDIR := /home/vadve/lattner/cvs/gcc_install_sparc +LLVMGCCARCH := sparcv9-sun-solaris2.8/3.4-llvm +LLVMGCCDIR := /home/vadve/lattner/local/sparc/llvm-gcc/ endif From lattner at cs.uiuc.edu Sun May 11 16:42:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 16:42:05 2003 Subject: [llvm-commits] CVS: llvm/test/Makefile.tests Message-ID: <200305112141.QAA04906@morpheus.cs.uiuc.edu> Changes in directory llvm/test: Makefile.tests updated: 1.55 -> 1.56 --- Log message: Remove dead makefile code --- Diffs of the changes: Index: llvm/test/Makefile.tests diff -u llvm/test/Makefile.tests:1.55 llvm/test/Makefile.tests:1.56 --- llvm/test/Makefile.tests:1.55 Sun May 11 13:49:10 2003 +++ llvm/test/Makefile.tests Sun May 11 16:41:43 2003 @@ -38,16 +38,9 @@ # LLVM Tool Definitions... # -ifdef LLVMGCCARCH # FIXME: Remove when new CFE is used on sparc as well! LCC = $(LLVMGCCDIR)/bin/gcc LCC1 = $(LLVMGCCDIR)/lib/gcc-lib/$(LLVMGCCARCH)/cc1 LGCCLD = $(TOOLS)/gccld -L$(LLVMGCCDIR)/lib/gcc-lib/$(LLVMGCCARCH) -L$(LLVMGCCDIR)/lib -else -LCC = $(LLVMGCCDIR)/bin/llvm-gcc -LCC1 = $(LLVMGCCDIR)/lib/gcc-lib/llvm/3.1/cc1 -LGCCLD = $(TOOLS)/gccld -L$(LLVMGCCDIR)/llvm/lib -endif - LLI = $(TOOLS)/lli LLC = $(TOOLS)/llc LAS = $(TOOLS)/as From lattner at cs.uiuc.edu Sun May 11 16:51:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 16:51:01 2003 Subject: [llvm-commits] CVS: llvm/www/docs/GettingStarted.html Message-ID: <200305112150.QAA01688@tank.cs.uiuc.edu> Changes in directory llvm/www/docs: GettingStarted.html updated: 1.8 -> 1.9 --- Log message: Add info about the LLVM_LIB_SEARCH_PATH envvar --- Diffs of the changes: Index: llvm/www/docs/GettingStarted.html diff -u llvm/www/docs/GettingStarted.html:1.8 llvm/www/docs/GettingStarted.html:1.9 --- llvm/www/docs/GettingStarted.html:1.8 Thu Feb 13 22:22:13 2003 +++ llvm/www/docs/GettingStarted.html Sun May 11 16:50:06 2003 @@ -80,6 +80,7 @@
    • Edit Makefile.config to set local paths. This includes setting the install location of the C frontend, and the various paths to the C and C++ compilers used to build LLVM itself. +
    • Set your LLVM_LIB_SEARCH_PATH environment variable.
    • gmake -k |& tee gnumake.out    # this is csh or tcsh syntax @@ -145,6 +146,15 @@

    • PURIFY = Path to the purify program. + In addition to settings in this file, you must set a + LLVM_LIB_SEARCH_PATH environment variable in your startup scripts. + This environment variable is used to locate "system" libraries like + "-lc" and "-lm" when linking. This variable should be set + to the absolute path for the bytecode-libs subdirectory of the C front-end + install. For example, + /home/vadve/lattner/local/x86/llvm-gcc/bytecode-libs for the X86 + version of the C front-end, on our research machines.

      +

      The location for LLVM object files

      @@ -462,7 +472,7 @@ -Last modified: Thu Feb 13 22:20:39 CST 2003 +Last modified: Sun May 11 16:49:46 CDT 2003 From lattner at cs.uiuc.edu Sun May 11 16:53:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 16:53:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/TEST.nightly.Makefile Message-ID: <200305112152.QAA09792@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: TEST.nightly.Makefile updated: 1.8 -> 1.9 --- Log message: Fix printing problem --- Diffs of the changes: Index: llvm/test/Programs/TEST.nightly.Makefile diff -u llvm/test/Programs/TEST.nightly.Makefile:1.8 llvm/test/Programs/TEST.nightly.Makefile:1.9 --- llvm/test/Programs/TEST.nightly.Makefile:1.8 Sun May 11 13:25:40 2003 +++ llvm/test/Programs/TEST.nightly.Makefile Sun May 11 16:52:08 2003 @@ -19,7 +19,7 @@ $(PROGRAMS_TO_TEST:%=Output/%.nightly.compile.report.txt): \ Output/%.nightly.compile.report.txt: Output/%.llvm.bc $(LGCCAS) @echo '$(LGCCAS) Output/$*.linked.rll -o /dev/null $(TIMEOPT) > $@ 2>&1' - -if ($(LGCCAS) Output/$*.linked.rll -o /dev/null $(TIMEOPT) > $@ 2>&1)\ + @if ($(LGCCAS) Output/$*.linked.rll -o /dev/null $(TIMEOPT) > $@ 2>&1)\ ;then \ echo "TEST-PASS: compile $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-compile: " >> $@;\ @@ -40,7 +40,7 @@ $(PROGRAMS_TO_TEST:%=Output/%.nightly.llc.report.txt): \ Output/%.nightly.llc.report.txt: Output/%.llvm.bc $(LLC) @echo 'time -p $(LLC) -f $(TIMEOPT) $< -o /dev/null) > $@ 2>&1' - @-if (time -p $(LLC) -f $(TIMEOPT) $< -o /dev/null) > $@ 2>&1; then \ + @if (time -p $(LLC) -f $(TIMEOPT) $< -o /dev/null) > $@ 2>&1; then \ echo "TEST-PASS: llc $(RELDIR)/$*" >> $@;\ echo -n "TEST-RESULT-llc: " >> $@;\ grep "Total Execution Time" $@.info >> $@;\ From lattner at cs.uiuc.edu Sun May 11 16:57:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 16:57:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/TEST.nightly.Makefile Message-ID: <200305112156.QAA09822@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: TEST.nightly.Makefile updated: 1.9 -> 1.10 --- Log message: Make sure to count CBE as tests --- Diffs of the changes: Index: llvm/test/Programs/TEST.nightly.Makefile diff -u llvm/test/Programs/TEST.nightly.Makefile:1.9 llvm/test/Programs/TEST.nightly.Makefile:1.10 --- llvm/test/Programs/TEST.nightly.Makefile:1.9 Sun May 11 16:52:08 2003 +++ llvm/test/Programs/TEST.nightly.Makefile Sun May 11 16:56:17 2003 @@ -58,6 +58,7 @@ Output/%.nightly.cbe.report.txt: Output/%.llvm.bc Output/%.diff-cbe $(LDIS) -head -n 100 Output/$*.diff-cbe > $@ @if test -f Output/$*.diff-cbe; then \ + echo "TEST-PASS: cbe $(RELDIR)/$*" >> $@;\ echo "TEST-RESULT-cbe: YES" >> $@;\ echo -n "TEST-RESULT-cbe-time: " >> $@;\ grep "^real" Output/$*.out-cbe.time >> $@;\ From lattner at cs.uiuc.edu Sun May 11 17:26:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 17:26:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Ptrdist-ft/Makefile Message-ID: <200305112225.RAA07228@morpheus.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Ptrdist-ft: Makefile updated: 1.1 -> 1.2 --- Log message: Tune down input size --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/Ptrdist-ft/Makefile diff -u llvm/test/Programs/MultiSource/Ptrdist-ft/Makefile:1.1 llvm/test/Programs/MultiSource/Ptrdist-ft/Makefile:1.2 --- llvm/test/Programs/MultiSource/Ptrdist-ft/Makefile:1.1 Tue Nov 5 12:47:50 2002 +++ llvm/test/Programs/MultiSource/Ptrdist-ft/Makefile Sun May 11 17:25:30 2003 @@ -1,8 +1,5 @@ LEVEL = ../../../.. PROG=ft -RUN_OPTIONS += 1000 2000 - - -#OBJS = ft.o graph.o item.o Fheap.o random.o +RUN_OPTIONS += 500 1000 include ../Makefile.multisrc From lattner at cs.uiuc.edu Sun May 11 17:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 17:42:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/sim/Makefile Message-ID: <200305112241.RAA14937@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/sim: Makefile updated: 1.1 -> 1.2 --- Log message: Don't time out the test --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/sim/Makefile diff -u llvm/test/Programs/MultiSource/sim/Makefile:1.1 llvm/test/Programs/MultiSource/sim/Makefile:1.2 --- llvm/test/Programs/MultiSource/sim/Makefile:1.1 Mon Apr 15 23:51:49 2002 +++ llvm/test/Programs/MultiSource/sim/Makefile Sun May 11 17:41:06 2003 @@ -3,5 +3,6 @@ PROG = sim CPPFLAGS = -DUNIX LDFLAGS = +RUNTIMELIMIT = 60 include ../Makefile.multisrc From lattner at cs.uiuc.edu Sun May 11 17:42:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 17:42:06 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile.programs Message-ID: <200305112241.RAA15143@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile.programs updated: 1.44 -> 1.45 --- Log message: Allow programs to override the runtime limit --- Diffs of the changes: Index: llvm/test/Programs/Makefile.programs diff -u llvm/test/Programs/Makefile.programs:1.44 llvm/test/Programs/Makefile.programs:1.45 --- llvm/test/Programs/Makefile.programs:1.44 Sun May 11 13:49:34 2003 +++ llvm/test/Programs/Makefile.programs Sun May 11 17:41:23 2003 @@ -59,9 +59,11 @@ DIFFPROG := $(PROGDIR)/DiffOutput.sh # RUNTIMELIMIT - The number of seconds we should wait before certain events -# timeout. This is overridable on the commandline. +# timeout. This is overridable on the commandline or in tests makefiles. # +ifndef RUNTIMELIMIT RUNTIMELIMIT := 40 +endif # RUNSAFELY - This program simply runs another program. If the program works # correctly, this script has no effect, otherwise it will do things like print a From lattner at cs.uiuc.edu Sun May 11 17:47:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 17:47:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LevelRaise/2002-11-04-ConstantSharing.ll Message-ID: <200305112246.RAA15348@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LevelRaise: 2002-11-04-ConstantSharing.ll added (r1.1) --- Log message: Checkin old test --- Diffs of the changes: Index: llvm/test/Regression/Transforms/LevelRaise/2002-11-04-ConstantSharing.ll diff -c /dev/null llvm/test/Regression/Transforms/LevelRaise/2002-11-04-ConstantSharing.ll:1.1 *** /dev/null Sun May 11 17:46:33 2003 --- llvm/test/Regression/Transforms/LevelRaise/2002-11-04-ConstantSharing.ll Sun May 11 17:46:23 2003 *************** *** 0 **** --- 1,11 ---- + + implementation + + bool %test(int *%X, uint* %Y) { + %A = cast int* %X to sbyte* + %B = cast uint* %Y to sbyte* + %c1 = seteq sbyte* %A, null + %c2 = seteq sbyte* %B, null + %c = and bool %c1, %c2 + ret bool %c + } From lattner at cs.uiuc.edu Sun May 11 20:58:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 20:58:00 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/aha/ Message-ID: <200305120157.UAA15957@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/aha: --- Log message: Directory /home/vadve/vadve/Research/DynOpt/CVSRepository/llvm/test/Programs/MultiSource/aha added to the repository --- Diffs of the changes: From lattner at cs.uiuc.edu Sun May 11 21:01:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 21:01:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/aha/Makefile aha.c aha.h aha.pdf read.me userfun.c Message-ID: <200305120200.VAA16139@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/aha: Makefile added (r1.1) aha.c added (r1.1) aha.h added (r1.1) aha.pdf added (r1.1) read.me added (r1.1) userfun.c added (r1.1) --- Log message: New test program --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/aha/Makefile diff -c /dev/null llvm/test/Programs/MultiSource/aha/Makefile:1.1 *** /dev/null Sun May 11 21:00:20 2003 --- llvm/test/Programs/MultiSource/aha/Makefile Sun May 11 21:00:10 2003 *************** *** 0 **** --- 1,5 ---- + LEVEL = ../../../.. + PROG = aha + CPPFLAGS = + LDFLAGS = + include ../Makefile.multisrc Index: llvm/test/Programs/MultiSource/aha/aha.c diff -c /dev/null llvm/test/Programs/MultiSource/aha/aha.c:1.1 *** /dev/null Sun May 11 21:00:20 2003 --- llvm/test/Programs/MultiSource/aha/aha.c Sun May 11 21:00:10 2003 *************** *** 0 **** --- 1,470 ---- + /* A Hacker's Assistant */ + + // Copyright (C) 2002 by Henry S. Warren, Jr. + #include + #include + #include "aha.h" + + // --------------------------- print_expr ------------------------------ + + void + print_expr(int opn) + { + int i, j, k; + + if (opn < RX) { // Immediate value. + if (-31 <= r[opn] && r[opn] <= 31) printf("%d", r[opn]); + else printf("0x%X", r[opn]); + } + else if (opn == RX) printf("x"); // First argument. + #if NARGS >= 2 + else if (opn == RY) printf("y"); // Second argument. + #endif + else { // opn is an instruction. + i = opn - RI0; + k = pgm[i].op; + printf("%s", isa[k].fun_name); + for (j = 0; j < isa[k].numopnds; j++) { + print_expr(pgm[i].opnd[j]); + if (j < isa[k].numopnds - 1) printf("%s", isa[k].op_name); + else printf(")"); + } + } + } + + // --------------------------- print_pgm ------------------------------- + + void + print_pgm() + { + int i, j, k, opndj; + + for (i = 0; i < numi; i++) { + k = pgm[i].op; + printf(" %-5s r%d,", isa[k].mnemonic, i + 1); + for (j = 0; j < isa[k].numopnds; j++) { + opndj = pgm[i].opnd[j]; + if (opndj < RX) { + opndj = r[opndj]; + if (opndj >= -31 && opndj <= 31) printf("%d", opndj); + else printf("0x%X", opndj); + } + else if (opndj == RX) printf( "rx"); + #if NARGS > 1 + else if (opndj == RY) printf("ry"); + #endif + else printf("r%d", opndj - RI0 + 1); + if (j < isa[k].numopnds - 1) printf(","); + } + if (debug) + printf(" ==> %d (0x%X)\n", r[i+RI0], r[i+RI0]); + else printf("\n"); + } // end for i + + /* Now print the program as an expression. */ + + printf(" Expr: "); + print_expr(numi - 1 + RI0); + printf("\n"); + } + + // -------------------- simulate_one_instruction ----------------------- + + inline void + simulate_one_instruction(int i) + { + int arg0, arg1, arg2; + + arg0 = r[pgm[i].opnd[0]]; + arg1 = r[pgm[i].opnd[1]]; + arg2 = r[pgm[i].opnd[2]]; + + r[i + RI0] = (*isa[pgm[i].op].proc)(arg0, arg1, arg2); + if (counters) counter[i] = counter[i] + 1; + return; + } + + // ----------------------------- check --------------------------------- + + int + check(int i) + { + int kx; + static int itrialx; // Init 0. + #if NARGS == 2 + static int itrialy; + #endif + + if (debug) { + #if NARGS == 1 + printf("\nSimulating with trial arg x = %d (0x%X):\n", + r[RX],r[RX]); + #else + printf("\nSimulating with (x, y) = (%d, %d) ((0x%X, 0x%X)):\n", + r[RX], r[RY], r[RX], r[RY]); + #endif + } + L: + simulate_one_instruction(i); // Simulate i'th insn, + if (i < numi - 1) {i = i + 1; goto L;} // and more if req'd + if (unacceptable) { // E.g., if divide by 0: + if (debug) printf("Unacceptable program (invalid operation).\n"); + unacceptable = 0; + return 0; + } + + if (debug) { + print_pgm(2); + printf("Computed result = %d, correct result = %d, %s\n", + r[numi-1+RI0], corr_result, r[numi-1+RI0] == corr_result ? "ok" : "fail"); + } + if (r[numi-1+RI0] != corr_result) // If not the correct + return 0; // result, failure. + + // Got the correct result. Check this program using all trial values. + + for (kx = 0; kx < NTRIALX - 1; kx++) { + itrialx += 1; + if (itrialx >= NTRIALX) itrialx = 0; + r[RX] = trialx[itrialx]; + #if NARGS == 1 + corr_result = correct_result[itrialx]; + #else + for (int ky = 0; ky < NTRIALY - 1; ky++) { + itrialy += 1; + if (itrialy >= NTRIALY) itrialy = 0; + r[RX] = trialx[itrialx]; + r[RY] = trialy[itrialy]; + corr_result = correct_result[itrialx][itrialy]; + #endif + + /* Now we simulate the current program, i.e., the instructions + from 0 to numi-1. The result of instruction i goes in + register i + RI0. */ + + if (debug) { + #if NARGS == 1 + printf("\nContinuing this pgm with arg x = %d (0x%X):\n", + r[RX], r[RX]); + #else + printf("\nContinuing this pgm with (x, y) = (%d, %d) ((0x%X, 0x%X)):\n", + r[RX], r[RY], r[RX], r[RY]); + #endif + } + for (i = 0; i < numi; i++) { // Simulate program from + simulate_one_instruction(i); // beginning to end. + } + if (unacceptable) {unacceptable = 0; return 0;} + if (debug) { + print_pgm(2); + printf("Computed result = %d, correct result = %d, %s\n", + r[numi+RI0-1], corr_result, r[numi+RI0-1] == corr_result ? "ok" : "fail"); + } + if (r[numi+RI0-1] != corr_result) return 0; + #if NARGS == 2 + } // end ky + #endif + } // end kx + return 1; // Passed all tests, found a + // probably correct program. + } + + // -------------------------- fix_operands ----------------------------- + + void + fix_operands(int i) + { + + /* This program fixes instruction i so that: + + (1) if it is the last instruction, at least one operand uses the + result of the immediately preceding instruction, and furthermore if + the second from last instruction does not use the result of its + predecsssor, then the last instruction must use that result also. + (2) not all operands are immediate values, and (We assume it would be + a waste of time to process an instruction with all immediate + operands). + (3) if it is commutative, operand 0 >= operand 1, + + It does these fixes by "increasing" the instruction by a minimal + amount, so that the incrementing of instructions is kept in order and no + legitimate instructions are skipped. + A hard part to understand is the logic of (1) above. Let us assume + for illustration that the program has four instructions (numi = 4). + Then when this subroutine is called to process the last instruction (i = + numi - 1), the operands may be in any of the configurations shown below. + The last instruction sets r4, the second from last instruction sets r3, + and its predecessor sets r2. ii denotes a register containing an + immediate value, or a register <= RY; in particular ii < r2. We assume + the last instruction ("op") has three input operands, as that is the + more difficult case, and that the second from last instruction does not + use r2. Therefore the last instruction must be altered so that it uses + both r2 and r3. + + operand: 0 1 2 0 1 2 + op r4,ii,ii,ii ==> op r4,r3,r2,ii Add r2 and r3. + op r4,ii,r2,ii ==> op r4,r3,r2,ii Add r3. + op r4,ii,r3,ii ==> op r4,r2,r3,ii Add r2. + op r4,ii,ii,r2 ==> op r4,r3,ii,r2 Add r3. + op r4,ii,r2,r2 ==> op r4,r3,r2,r2 Add r3. + op r4,ii,r3,r2 ==> no change + op r4,ii,ii,r3 ==> op r4,r2,ii,r3 Add r2. + op r4,ii,r2,r3 ==> no change + op r4,ii,r3,r3 ==> op r4,r2,r3,r3 + + These are the only possibilities. The first input operand cannot be + r2 or r3, because if it were, then it must have just been incremented + from r1 or r2 resp., and in this case "increment" does not call + "fix_operands." + The first row above means that if none of the last instruction's + operands are r2 or r3, then the change that adds r2 and r3 and that + "minimizes" the resulting instruction is to change operand 0 to r3 and + operand 1 to r2. The second row shows a case in which r2 is already + present, but r3 is not. The minimal change is to change operand 0 to r3. + Examination of all the possibilities reveals that a workable simple + rule is: + (1) If r3 is not used, then change operand 0 to be r3. + (2) Then, if r2 is not used, change operand 0 to r2 unless that + decreases the instruction, in which case change operand 1 to r2. + These rules are coded in the block headed by "if (i == numi - 1)". + It might seem that the program should test that pgm[i].opnd[0] is not + equal to rs or rt; however, as noted above operand 0 is never equal + to those registers at this point. + This scheme is sufficient to ensure that if numi = 3, no trial + program has an unused computed value. If numi = 4, a small percentage + of trial programs will have an unused computed value. Incorporation + of the r2 part of it improved the execution time by about a factor of + 1.4 if numi = 3, and a factor of 1.8 if numi = 4. If numi = 5, there + is probably a substantial percentage of trial programs with one or + more unused computed values; it hasn't been tried. */ + + int rs, rt, k; + + k = pgm[i].op; + + if (i == numi - 1) { // If this is the last insn: + rs = numi + RI0 - 2; // Second from last reg. + if (pgm[i].opnd[1] != rs && pgm[i].opnd[2] != rs) { + pgm[i].opnd[0] = rs; + } + rt = rs - 1; // Third from last reg. + if (pgm[i-1].opnd[0] != rt && pgm[i-1].opnd[1] != rt && + pgm[i-1].opnd[2] != rt && pgm[i].opnd[1] != rt && + pgm[i].opnd[2] != rt && rt >= RI0) { + + // The last instruction needs to reference rt. + + if (pgm[i].opnd[0] < rt) pgm[i].opnd[0] = rt; + else if (isa[k].numopnds > 1) pgm[i].opnd[1] = rt; + + // else (unary op), forget it. + } + } + + if (isa[k].commutative) { + if (pgm[i].opnd[0] < pgm[i].opnd[1]) + pgm[i].opnd[0] = pgm[i].opnd[1]; + return; // No need to do next check, as opnd[0] + } // is always a reg containing a variable. + + if (i != numi - 1) { + if (pgm[i].opnd[0] < RX && pgm[i].opnd[1] < RX && + pgm[i].opnd[2] < RX) { + if (isa[k].commutative) abort(); + pgm[i].opnd[0] = RX; + } + } + } + + // --------------------------- increment ------------------------------- + + inline int + increment(void) + { + + /* This routine "increments" the instruction list, in a manner + similar to counting. The instruction list changes basically + like this: + + i0 r0,r0 i0 r0,r0 i0 r0,r0 i0 r0,r0 + i0 r0,r0 ==> i0 r0,r0 ==> i0 r0,r0 ==> i0 r0,r0 etc. + i0 r0,r0 i0 r1,r0 i0 r2,r0 i0 r0,r1 + + The bottom left operand is tested. If it has not reached its + maximum value, it is incremented. If it has reached its maximum + value, it is reset to its starting value and the operand to its right + is incremented if possible. If all operands have reached their + maxima, the last instruction is replaced with the next instruction + in the isa list, if possible, etc. + The returned value is the lowest index i of the instructions + modified, or -1 if the instruction list cannot be incremented anymore + ("done"). + As far as incrementing goes, there are only three types of operands: + + 1. Goes through the ordinary immediate values, skips the shift + immediate values, and then goes through the registers. + 2. Goes through the shift immediate values followed by the registers. + 3. Goes through the registers only. + + Which range an operand is in can be determined by its register number + alone, so we don't need operand types in the ISA. However, opnd[0] + of a commutative op is an exception in that it doesn't go through + all the register values; it skips register values for which it is + less than opnd[1]. + There's no doubt a faster way to program this, maybe by using + some fairly large tables. */ + + int i, j, k, opndj, nopnds; + + for (i = numi - 1; i >= 0; i--) { + k = pgm[i].op; + nopnds = isa[k].numopnds; + for (j = 0; j < nopnds; j++) { + opndj = pgm[i].opnd[j]; + + if (opndj < NIM - 1) { // If ordinary imm. and not last, + pgm[i].opnd[j] += 1; // increment the operand. + break; + } + else if (opndj == NIM - 1) { // If last ordinary imm. operand, + pgm[i].opnd[j] = RX; // skip to first register. + break; + } + else if (opndj < i + RI0 - 1) {// If shift imm. or reg and not + pgm[i].opnd[j] += 1; // last, increment the operand. + break; + } + // We're at the end for opnd j. + pgm[i].opnd[j] = isa[k].opndstart[j]; // Reset it and + // increment next operand to + // its right. + } // end for j + + if (j == 0) // If we just incremented the + return i; // leftmost operand, return; the + // following check is not necessary. + if (j < nopnds) { + + /* We just incremented some operand other than the rightmost, + which means we reset one or more operands. Must ensure that if + the instruction is commutative then opnd[0] >= opnd[1], that + the operands are not all immediate values, and if this is the + last instruction, that at least one operand refers to the + second from last instruction and possibly to the instruction + before that. */ + + fix_operands(i); + return i; + } + + /* Have gone through all of insn i's opnds. + Increment the instruction itself (if possible). */ + + if (k < NUM_INSNS_IN_ISA - 1) { + k = k + 1; // Increment to next isa instruction. + pgm[i].op = k; + pgm[i].opnd[0] = isa[k].opndstart[0]; + pgm[i].opnd[1] = isa[k].opndstart[1]; + pgm[i].opnd[2] = isa[k].opndstart[2]; + + fix_operands(i); + return i; + } + + /* Cannot increment to next isa insn. Reset it to the first + isa insn and look at next insn down in the program. Furthermore, + if the insn being reset is the last insn in the program, make + its first opnd pick up the previous insn's result. */ + + pgm[i].op = 0; // Index first insn in isa. + pgm[i].opnd[0] = isa[0].opndstart[0]; + pgm[i].opnd[1] = isa[0].opndstart[1]; + pgm[i].opnd[2] = isa[0].opndstart[2]; + + fix_operands(i); + } // end for i + return -1; // Return "done" indication. + } + + // ----------------------------- search -------------------------------- + + int + search(void) + { + + int ok, i, num_solutions; + + #if NARGS == 1 + r[RX] = trialx[0]; // Must initialize these for + corr_result = correct_result[0]; // speed-up thing in "check." + #else + r[RX] = trialx[0]; + r[RY] = trialy[0]; + corr_result = correct_result[0][0]; + #endif + num_solutions = 0; + i = 0; + do { + ok = check(i); // Simulate the program from i on. + if (ok) { + num_solutions += 1; + printf("\nFound a %d-operation program:\n", numi); + print_pgm(3); + if (num_solutions == 10) return num_solutions; // bail out early + } + i = increment(); // Increment to next program. + } while (i >= 0); + return num_solutions; + } + + // -------------------------- Main Program ----------------------------- + + int main(int argc, char *argv[]) { + int i, num_sol = 0; + + for (numi = 1; numi <= MAXNUMI && num_sol == 0; ++numi) { + printf("Searching for programs with %d operations.\n", numi); + + // Compute all the correct answers and save them in an array. + + for (i = 0; i < NTRIALX; i++) { + #if NARGS == 1 + correct_result[i] = userfun(trialx[i]); + #else + for (int j = 0; j < NTRIALY; j++) + correct_result[i][j] = userfun(trialx[i], trialy[j]); + #endif + } + + /* Preload the instruction array with the first instruction and + the lowest register number, with copies of this instruction + filling the whole array from 0 to numi - 1. */ + + for (i = 0; i < numi; i++) { + pgm[i].op = 0; // Index first insn in isa. + pgm[i].opnd[0] = isa[0].opndstart[0]; + pgm[i].opnd[1] = isa[0].opndstart[1]; + pgm[i].opnd[2] = isa[0].opndstart[2]; + + /* Ensure that the instruction does not have all immediate + operands, etc. */ + + fix_operands(i); + } + + // Check the above program, generate the next, check it, etc. + num_sol = search(); + + printf("Found %d solutions.\n", num_sol); + if (counters) { + int total = 0; + printf("Counters = "); + for (i = 0; i < numi; i++) { + printf("%d, ", counter[i]); + total = total + counter[i]; + } + printf("total = %d\n", total); + } + } + return 0; + } Index: llvm/test/Programs/MultiSource/aha/aha.h diff -c /dev/null llvm/test/Programs/MultiSource/aha/aha.h:1.1 *** /dev/null Sun May 11 21:00:20 2003 --- llvm/test/Programs/MultiSource/aha/aha.h Sun May 11 21:00:10 2003 *************** *** 0 **** --- 1,195 ---- + // Copyright (C) 2002 by Henry S. Warren, Jr. + const int debug = 0; // 0 or 1; debugging printouts if 1. + const int counters = 1; // 0 or 1; count number of evaluations. + #define NARGS 1 // Number of args in userfun, 1 or 2. + + /* A note about the registers: + + They are divided into four groups. The first group, starting with + register 0, holds ordinary immediate values. The second group, starting + with register NIM, holds the shift immediate values. The next 1 or 2 + regs are the arguments to the user-defined function. The last group + holds the results of computations done by the trial programs. + + 0 Start of ordinary immediate values (those given by IMMEDS) + NIM Start of shift immediate values (those given by SHIMMEDS) + RX First (or only) user function argument + RY Second user function argument + RI0 Result of instruction 0 goes here + RI0 + i Result of instruction i goes here + where: + NIM = number of ordinary immediate values + NSHIM = number of shift immediate values + */ + + #define MAXNEG 0x80000000 + #define MAXPOS 0x7FFFFFFF + #define NBSM 63 // Shift mask. Use 63 for mod 64 + // shifts, or 31 for mod 32. + + int trialx[] = {1, 0, -1, MAXNEG, MAXPOS, \ + MAXNEG + 1, MAXPOS - 1, 0x01234567, 0x89ABCDEF, -2, 2, -3, 3, \ + -64, 64, -5, -31415}; + #if NARGS == 2 + int trialy[] = {0}; + #endif + // First three values of IMMEDS must be 0, -1, and 1. + #define IMMEDS 0, -1, 1, MAXNEG, -2, 2, 3 + #define SHIMMEDS 1, 2, 30, 31 + + int dummy1[] = {IMMEDS}; // These get optimized out of existence. + int dummy2[] = {SHIMMEDS}; + + #define NIM (int)(sizeof(dummy1)/sizeof(dummy1[0])) + #define NSHIM (int)(sizeof(dummy2)/sizeof(dummy2[0])) + #define RX (NIM + NSHIM) // First (or only) user function argument + #define RY (RX + 1) // Second user function argument + #define RI0 (RX + NARGS) // Result of instruction 0 goes here + + int unacceptable; // Code below sets this to 1 for an + // unacceptable operation, such as + // divide by 0. It is initially 0. + + /* Collection of simulator routines for the instructions in the isa. */ + int neg(int x, int y, int z) {return -x;} + int _not(int x, int y, int z) {return ~x;} + int pop(int xx, int y, int z) { + unsigned x = xx; + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x = x + (x << 8); + x = x + (x << 16); + return x >> 24; + } + + int nlz(int xx, int y, int z) { + unsigned x = xx; + int n; + + if (x == 0) return(32); + n = 0; + if (x <= 0x0000FFFF) {n = n +16; x = x <<16;} + if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;} + if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;} + if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;} + if (x <= 0x7FFFFFFF) {n = n + 1;} + return n; + } + + int rev(int xi, int y, int z) { + unsigned x = xi; + x = (x & 0x55555555) << 1 | ((x >> 1) & 0x55555555); + x = (x & 0x33333333) << 2 | ((x >> 2) & 0x33333333); + x = (x & 0x0F0F0F0F) << 4 | ((x >> 4) & 0x0F0F0F0F); + x = (x << 24) | ((x & 0xFF00) << 8) | + ((x >> 8) & 0xFF00) | (x >> 24); + return x; + } + + int add (int x, int y, int z) {return x + y;} + int sub (int x, int y, int z) {return x - y;} + int mul (int x, int y, int z) {return x * y;} + /* For division overflow we return arbitrary values, hoping they fail + to be part of a solution. (User must check solutions, in general.) */ + int divide (int x, int y, int z) { + if (y == 0 || (y == -1 && x == (int)0x80000000)) + {unacceptable = 1; return 0;} + else return x/y;} + int divu(int x, int y, int z) { + if (y == 0) {unacceptable = 1; return 0;} + else return (unsigned)x/(unsigned)y;} + int _and(int x, int y, int z) {return x & y;} + int _or (int x, int y, int z) {return x | y;} + int _xor(int x, int y, int z) {return x ^ y;} + int rotl(int x, int y, int z) {int s = y & NBSM; + return x << s | (unsigned)x >> (32 - s);} + int shl (int x, int y, int z) {int s = y & NBSM; + if (s >= 32) return 0; else return x << s;} + int shr(int x, int y, int z) {int s = y & NBSM; + if (s >= 32) return 0; else return (unsigned)x >> s;} + int shrs(int x, int y, int z) {int s = y & NBSM; + if (s >= 32) return x >> 31; else return x >> s;} + int cmpeq(int x, int y, int z) {return x == y;} + int cmplt(int x, int y, int z) {return x < y;} + int cmpltu(int x, int y, int z) {return (unsigned)(x) < (unsigned)(y);} + int seleq(int x, int y, int z) {return x == 0 ? y : z;} + int sellt(int x, int y, int z) {return x < 0 ? y : z;} + int selle(int x, int y, int z) {return x <= 0 ? y : z;} + + // The machine's instruction set: + // Note: Commutative ops are commutative in operands 0 and 1. + struct { + int (*proc)(int, int, int); // Procedure for simulating the op. + int numopnds; // Number of operands, 1 to 3. + int commutative; // 1 if opnds 0 and 1 commutative. + int opndstart[3]; // Starting reg no. for each operand. + char *mnemonic; // Name of op, for printing. + char *fun_name; // Function name, for printing. + char *op_name; // Operator name, for printing. + } isa[] = { + {neg, 1, 0, {RX, 0, 0}, "neg", "-(", "" }, // Negate. + {_not, 1, 0, {RX, 0, 0}, "not", "~(", "" }, // One's-complement. + // {pop, 1, 0, {RX, 0, 0}, "pop", "pop(", "" }, // Population count. + // {nlz, 1, 0, {RX, 0, 0}, "nlz", "nlz(", "" }, // Num leading 0's. + // {rev, 1, 0, {RX, 0, 0}, "rev", "rev(", "" }, // Bit reversal. + {add, 2, 1, {RX, 2, 0}, "add", "(", " + " }, // Add. + {sub, 2, 0, { 2, 2, 0}, "sub", "(", " - " }, // Subtract. + {mul, 2, 1, {RX, 3, 0}, "mul", "(", "*" }, // Multiply. + {divide, 2, 0, { 1, 3, 0}, "div", "(", "/" }, // Divide signed. + {divu, 2, 0, { 1, 1, 0}, "divu", "(", " /u " }, // Divide unsigned. + {_and, 2, 1, {RX, 2, 0}, "and", "(", " & " }, // AND. + {_or, 2, 1, {RX, 2, 0}, "or", "(", " | " }, // OR. + {_xor, 2, 1, {RX, 2, 0}, "xor", "(", " ^ " }, // XOR. + // {rotl, 2, 0, { 1,NIM, 0}, "rotl", "(", " <>u "}, // Shift right. + {shrs, 2, 0, { 3,NIM, 0}, "shrs", "(", " >>s "}, // Shift right signed. + // {cmpeq, 2, 1, {RX, 0, 0}, "cmpeq", "(", " == " }, // Compare equal. + // {cmplt, 2, 0, { 0, 0, 0}, "cmplt", "(", " < " }, // Compare less than. + // {cmpltu, 2, 0, { 1, 1, 0}, "cmpltu","(", " 0) return 1; // x > 0 predicate. + // else return 0; // Turn off div & divu. + // Found a new formula for HD. + + // if (x >= 32) return 0; + // return 1 << (unsigned)x; + + // return 3*x + 1; + + // if (x >= 0) return x; // Absolute value. + // else return -x; + + return (x & 0xfffffffc) | ((x & 1) << 1) | ((x & 2) >> 1); + // Swap rightmost 2 bits. + } From lattner at cs.uiuc.edu Sun May 11 21:04:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 21:04:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/aha/aha.c Message-ID: <200305120203.VAA16270@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/aha: aha.c updated: 1.1 -> 1.2 --- Log message: Bail out earlier --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/aha/aha.c diff -u llvm/test/Programs/MultiSource/aha/aha.c:1.1 llvm/test/Programs/MultiSource/aha/aha.c:1.2 --- llvm/test/Programs/MultiSource/aha/aha.c:1.1 Sun May 11 21:00:10 2003 +++ llvm/test/Programs/MultiSource/aha/aha.c Sun May 11 21:03:48 2003 @@ -410,7 +410,7 @@ num_solutions += 1; printf("\nFound a %d-operation program:\n", numi); print_pgm(3); - if (num_solutions == 10) return num_solutions; // bail out early + if (num_solutions == 5) return num_solutions; // bail out early } i = increment(); // Increment to next program. } while (i >= 0); From lattner at cs.uiuc.edu Sun May 11 21:15:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 21:15:00 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/ExecutionEngine.h Message-ID: <200305120214.VAA16620@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli: ExecutionEngine.h updated: 1.3 -> 1.4 --- Log message: Make sure that globals are emitted AFTER the passmanager is set up for the JIT, because the globals may refer to functions that need to be compiled! --- Diffs of the changes: Index: llvm/tools/lli/ExecutionEngine.h diff -u llvm/tools/lli/ExecutionEngine.h:1.3 llvm/tools/lli/ExecutionEngine.h:1.4 --- llvm/tools/lli/ExecutionEngine.h:1.3 Thu May 8 22:29:03 2003 +++ llvm/tools/lli/ExecutionEngine.h Sun May 11 21:14:26 2003 @@ -30,7 +30,6 @@ void setTargetData(const TargetData &td) { TD = &td; - emitGlobals(); } public: ExecutionEngine(Module *M) : CurMod(*M) { @@ -81,7 +80,7 @@ // virtual void *getPointerToFunction(const Function *F) = 0; -private: +protected: void emitGlobals(); public: // FIXME: protected: // API shared among subclasses From lattner at cs.uiuc.edu Sun May 11 21:15:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 21:15:06 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/Interpreter/Interpreter.cpp Message-ID: <200305120214.VAA16628@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/Interpreter: Interpreter.cpp updated: 1.4 -> 1.5 --- Log message: Make sure that globals are emitted AFTER the passmanager is set up for the JIT, because the globals may refer to functions that need to be compiled! --- Diffs of the changes: Index: llvm/tools/lli/Interpreter/Interpreter.cpp diff -u llvm/tools/lli/Interpreter/Interpreter.cpp:1.4 llvm/tools/lli/Interpreter/Interpreter.cpp:1.5 --- llvm/tools/lli/Interpreter/Interpreter.cpp:1.4 Thu May 8 11:18:31 2003 +++ llvm/tools/lli/Interpreter/Interpreter.cpp Sun May 11 21:14:30 2003 @@ -34,6 +34,7 @@ initializeExecutionEngine(); initializeExternalFunctions(); CW.setModule(M); // Update Writer + emitGlobals(); } /// run - Start execution with the specified function and arguments. From lattner at cs.uiuc.edu Sun May 11 21:15:11 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 21:15:11 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/JIT/JIT.cpp Message-ID: <200305120214.VAA16636@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/JIT: JIT.cpp updated: 1.1 -> 1.2 --- Log message: Make sure that globals are emitted AFTER the passmanager is set up for the JIT, because the globals may refer to functions that need to be compiled! --- Diffs of the changes: Index: llvm/tools/lli/JIT/JIT.cpp diff -u llvm/tools/lli/JIT/JIT.cpp:1.1 llvm/tools/lli/JIT/JIT.cpp:1.2 --- llvm/tools/lli/JIT/JIT.cpp:1.1 Mon Dec 23 18:01:05 2002 +++ llvm/tools/lli/JIT/JIT.cpp Sun May 11 21:14:34 2003 @@ -33,6 +33,7 @@ MCE = createEmitter(*this); // Initialize MCE setupPassManager(); registerCallback(); + emitGlobals(); } int VM::run(const std::string &FnName, const std::vector &Args) { From lattner at cs.uiuc.edu Sun May 11 21:28:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 21:28:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll Message-ID: <200305120227.VAA16891@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: 2003-05-11-PHIRegAllocBug.ll added (r1.1) --- Log message: New testcase that crashes Jello --- Diffs of the changes: Index: llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll diff -c /dev/null llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll:1.1 *** /dev/null Sun May 11 21:27:15 2003 --- llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll Sun May 11 21:27:05 2003 *************** *** 0 **** --- 1,15 ---- + target endian = little + target pointersize = 32 + + implementation + + int %main(int, sbyte**) { + entry: + br bool false, label %then, label %endif + then: + br label %endif + endif: + %x.0 = phi uint [ 4, %entry ], [ 27, %then ] + %result.0 = phi int [ 32, %then ], [ 0, %entry ] + ret int 0 + } From lattner at cs.uiuc.edu Sun May 11 21:32:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 21:32:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll Message-ID: <200305120231.VAA16936@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: 2003-05-11-PHIRegAllocBug.ll updated: 1.1 -> 1.2 --- Log message: Simplify testcase a bit more --- Diffs of the changes: Index: llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll diff -u llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll:1.1 llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll:1.2 --- llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll:1.1 Sun May 11 21:27:05 2003 +++ llvm/test/Regression/Jello/2003-05-11-PHIRegAllocBug.ll Sun May 11 21:31:48 2003 @@ -3,13 +3,13 @@ implementation -int %main(int, sbyte**) { +int %main() { entry: - br bool false, label %then, label %endif + br label %endif then: br label %endif endif: - %x.0 = phi uint [ 4, %entry ], [ 27, %then ] - %result.0 = phi int [ 32, %then ], [ 0, %entry ] + %x = phi uint [ 4, %entry ], [ 27, %then ] + %result = phi int [ 32, %then ], [ 0, %entry ] ret int 0 } From lattner at cs.uiuc.edu Sun May 11 22:52:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 22:52:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/LiveVariables.h Message-ID: <200305120351.WAA20528@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: LiveVariables.h updated: 1.2 -> 1.3 --- Log message: Expand API for updating live var info. Expose iterators, not const-iterators. Rename method that was VERY misleading --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/LiveVariables.h diff -u llvm/include/llvm/CodeGen/LiveVariables.h:1.2 llvm/include/llvm/CodeGen/LiveVariables.h:1.3 --- llvm/include/llvm/CodeGen/LiveVariables.h:1.2 Wed May 7 15:07:58 2003 +++ llvm/include/llvm/CodeGen/LiveVariables.h Sun May 11 22:51:30 2003 @@ -72,6 +72,7 @@ /// liveness for values that are not in this set. /// std::vector AllocatablePhysicalRegisters; + private: // Intermediate data structures /// BBMap - Maps LLVM basic blocks to their corresponding machine basic block. @@ -89,30 +90,60 @@ /// killed_iterator - Iterate over registers killed by a machine instruction /// - typedef std::multimap::const_iterator killed_iterator; + typedef std::multimap::iterator killed_iterator; /// killed_begin/end - Get access to the range of registers killed by a /// machine instruction. - killed_iterator killed_begin(MachineInstr *MI) const { + killed_iterator killed_begin(MachineInstr *MI) { return RegistersKilled.lower_bound(MI); } - killed_iterator killed_end(MachineInstr *MI) const { + killed_iterator killed_end(MachineInstr *MI) { return RegistersKilled.upper_bound(MI); } + std::pair + killed_range(MachineInstr *MI) { + return RegistersKilled.equal_range(MI); + } - killed_iterator dead_begin(MachineInstr *MI) const { + killed_iterator dead_begin(MachineInstr *MI) { return RegistersDead.lower_bound(MI); } - killed_iterator dead_end(MachineInstr *MI) const { + killed_iterator dead_end(MachineInstr *MI) { return RegistersDead.upper_bound(MI); } + std::pair + dead_range(MachineInstr *MI) { + return RegistersDead.equal_range(MI); + } - /// addVirtualRegisterKill - Add information about the fact that the specified + //===--------------------------------------------------------------------===// + // API to update live variable information + + /// addVirtualRegisterKilled - Add information about the fact that the + /// specified register is killed after being used by the specified + /// instruction. + /// + void addVirtualRegisterKilled(unsigned IncomingReg, MachineInstr *MI) { + RegistersKilled.insert(std::make_pair(MI, IncomingReg)); + } + + /// removeVirtualRegistersKilled - Remove all of the specified killed + /// registers from the live variable information. + void removeVirtualRegistersKilled(killed_iterator B, killed_iterator E) { + RegistersKilled.erase(B, E); + } + + /// addVirtualRegisterDead - Add information about the fact that the specified /// register is dead after being used by the specified instruction. /// - void addVirtualRegisterKill(unsigned IncomingReg, MachineInstr *MI) { + void addVirtualRegisterDead(unsigned IncomingReg, MachineInstr *MI) { RegistersDead.insert(std::make_pair(MI, IncomingReg)); + } + + /// removeVirtualRegistersKilled - Remove all of the specified killed + /// registers from the live variable information. + void removeVirtualRegistersDead(killed_iterator B, killed_iterator E) { + RegistersDead.erase(B, E); } virtual void getAnalysisUsage(AnalysisUsage &AU) const { From lattner at cs.uiuc.edu Sun May 11 22:55:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 22:55:00 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLocal.cpp Message-ID: <200305120354.WAA20548@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLocal.cpp updated: 1.14 -> 1.15 --- Log message: Fix tab infestation! --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocLocal.cpp diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.14 llvm/lib/CodeGen/RegAllocLocal.cpp:1.15 --- llvm/lib/CodeGen/RegAllocLocal.cpp:1.14 Sun May 4 17:51:30 2003 +++ llvm/lib/CodeGen/RegAllocLocal.cpp Sun May 11 22:54:14 2003 @@ -467,22 +467,22 @@ // spilled to memory. // for (LiveVariables::killed_iterator KI = LV->killed_begin(MI), - KE = LV->killed_end(MI); KI != KE; ++KI) { + KE = LV->killed_end(MI); KI != KE; ++KI) { unsigned VirtReg = KI->second; - unsigned PhysReg = VirtReg; - if (VirtReg >= MRegisterInfo::FirstVirtualRegister) { - std::map::iterator I = - Virt2PhysRegMap.find(VirtReg); - assert(I != Virt2PhysRegMap.end()); - PhysReg = I->second; - Virt2PhysRegMap.erase(I); - } - - if (PhysReg) { - DEBUG(std::cerr << "V: " << VirtReg << " P: " << PhysReg - << " Killed by: " << *MI); - removePhysReg(PhysReg); - } + unsigned PhysReg = VirtReg; + if (VirtReg >= MRegisterInfo::FirstVirtualRegister) { + std::map::iterator I = + Virt2PhysRegMap.find(VirtReg); + assert(I != Virt2PhysRegMap.end()); + PhysReg = I->second; + Virt2PhysRegMap.erase(I); + } + + if (PhysReg) { + DEBUG(std::cerr << "V: " << VirtReg << " P: " << PhysReg + << " Killed by: " << *MI); + removePhysReg(PhysReg); + } } } @@ -501,9 +501,9 @@ if (const unsigned *ImplicitDefs = TID.ImplicitDefs) for (unsigned i = 0; ImplicitDefs[i]; ++i) { unsigned Reg = ImplicitDefs[i]; - spillPhysReg(MBB, I, Reg); - PhysRegsUseOrder.push_back(Reg); - PhysRegsUsed[Reg] = 0; // It is free and reserved now + spillPhysReg(MBB, I, Reg); + PhysRegsUseOrder.push_back(Reg); + PhysRegsUsed[Reg] = 0; // It is free and reserved now } // Okay, we have allocated all of the source operands and spilled any values @@ -513,19 +513,19 @@ // for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) if (MI->getOperand(i).opIsDef() && - MI->getOperand(i).isVirtualRegister()) { + MI->getOperand(i).isVirtualRegister()) { unsigned DestVirtReg = MI->getOperand(i).getAllocatedRegNum(); unsigned DestPhysReg; - // If DestVirtReg already has a value, forget about it. Why doesn't - // getReg do this right? - std::map::iterator DestI = - Virt2PhysRegMap.find(DestVirtReg); - if (DestI != Virt2PhysRegMap.end()) { - unsigned PhysReg = DestI->second; - Virt2PhysRegMap.erase(DestI); - removePhysReg(PhysReg); - } + // If DestVirtReg already has a value, forget about it. Why doesn't + // getReg do this right? + std::map::iterator DestI = + Virt2PhysRegMap.find(DestVirtReg); + if (DestI != Virt2PhysRegMap.end()) { + unsigned PhysReg = DestI->second; + Virt2PhysRegMap.erase(DestI); + removePhysReg(PhysReg); + } if (TM->getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) { // must be same register number as the first operand @@ -536,12 +536,12 @@ "Two address instruction invalid!"); DestPhysReg = MI->getOperand(1).getAllocatedRegNum(); - liberatePhysReg(MBB, I, DestPhysReg); + liberatePhysReg(MBB, I, DestPhysReg); assignVirtToPhysReg(DestVirtReg, DestPhysReg); } else { DestPhysReg = getReg(MBB, I, DestVirtReg); } - markVirtRegModified(DestVirtReg); + markVirtRegModified(DestVirtReg); MI->SetMachineOperandReg(i, DestPhysReg); // Assign the output register } @@ -550,22 +550,22 @@ // kill them now. // for (LiveVariables::killed_iterator KI = LV->dead_begin(MI), - KE = LV->dead_end(MI); KI != KE; ++KI) { + KE = LV->dead_end(MI); KI != KE; ++KI) { unsigned VirtReg = KI->second; - unsigned PhysReg = VirtReg; - if (VirtReg >= MRegisterInfo::FirstVirtualRegister) { - std::map::iterator I = - Virt2PhysRegMap.find(VirtReg); - assert(I != Virt2PhysRegMap.end()); - PhysReg = I->second; - Virt2PhysRegMap.erase(I); - } - - if (PhysReg) { - DEBUG(std::cerr << "V: " << VirtReg << " P: " << PhysReg - << " dead after: " << *MI); - removePhysReg(PhysReg); - } + unsigned PhysReg = VirtReg; + if (VirtReg >= MRegisterInfo::FirstVirtualRegister) { + std::map::iterator I = + Virt2PhysRegMap.find(VirtReg); + assert(I != Virt2PhysRegMap.end()); + PhysReg = I->second; + Virt2PhysRegMap.erase(I); + } + + if (PhysReg) { + DEBUG(std::cerr << "V: " << VirtReg << " P: " << PhysReg + << " dead after: " << *MI); + removePhysReg(PhysReg); + } } } } @@ -582,9 +582,9 @@ PhysRegsUsed.begin()->first); for (std::map::iterator I = Virt2PhysRegMap.begin(), - E = Virt2PhysRegMap.end(); I != E; ++I) + E = Virt2PhysRegMap.end(); I != E; ++I) std::cerr << "Register still mapped: " << I->first << " -> " - << I->second << "\n"; + << I->second << "\n"; assert(Virt2PhysRegMap.empty() && "Virtual registers still in phys regs?"); assert(PhysRegsUseOrder.empty() && "Physical regs still allocated?"); From lattner at cs.uiuc.edu Sun May 11 22:56:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 22:56:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/PHIElimination.cpp Message-ID: <200305120355.WAA20561@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: PHIElimination.cpp updated: 1.3 -> 1.4 --- Log message: * Fix several comments * Update LiveVar info better, fixing bug: Jello/2003-05-11-PHIRegAllocBug.ll --- Diffs of the changes: Index: llvm/lib/CodeGen/PHIElimination.cpp diff -u llvm/lib/CodeGen/PHIElimination.cpp:1.3 llvm/lib/CodeGen/PHIElimination.cpp:1.4 --- llvm/lib/CodeGen/PHIElimination.cpp:1.3 Thu Jan 16 12:06:43 2003 +++ llvm/lib/CodeGen/PHIElimination.cpp Sun May 11 22:55:21 2003 @@ -71,7 +71,7 @@ const TargetRegisterClass *RC = MF.getSSARegMap()->getRegClass(DestReg); unsigned IncomingReg = MF.getSSARegMap()->createVirtualRegister(RC); - // Insert a register to register copy in the top of the current block (by + // Insert a register to register copy in the top of the current block (but // after any remaining phi nodes) which copies the new incoming register // into the phi node destination. // @@ -79,18 +79,47 @@ if (AfterPHIsIt != MBB.end()) while ((*AfterPHIsIt)->getOpcode() == TargetInstrInfo::PHI) ++AfterPHIsIt; RegInfo->copyRegToReg(MBB, AfterPHIsIt, DestReg, IncomingReg, RC); + + // Update live variable information if there is any... + if (LV) { + MachineInstr *PHICopy = *(AfterPHIsIt-1); - // Add information to LiveVariables to know that the incoming value is dead - if (LV) LV->addVirtualRegisterKill(IncomingReg, *(AfterPHIsIt-1)); + // Add information to LiveVariables to know that the incoming value is + // dead. This says that the register is dead, not killed, because we + // cannot use the live variable information to indicate that the variable + // is defined in multiple entry blocks. Instead, we pretend that this + // instruction defined it and killed it at the same time. + // + LV->addVirtualRegisterDead(IncomingReg, PHICopy); + + // Since we are going to be deleting the PHI node, if it is the last use + // of any registers, or if the value itself is dead, we need to move this + // information over to the new copy we just inserted... + // + std::pair + RKs = LV->killed_range(MI); + if (RKs.first != RKs.second) { + for (LiveVariables::killed_iterator I = RKs.first; I != RKs.second; ++I) + LV->addVirtualRegisterKilled(I->second, PHICopy); + LV->removeVirtualRegistersKilled(RKs.first, RKs.second); + } + + RKs = LV->dead_range(MI); + if (RKs.first != RKs.second) { + for (LiveVariables::killed_iterator I = RKs.first; I != RKs.second; ++I) + LV->addVirtualRegisterDead(I->second, PHICopy); + LV->removeVirtualRegistersDead(RKs.first, RKs.second); + } + } - // Now loop over all of the incoming arguments turning them into copies into + // Now loop over all of the incoming arguments, changing them to copy into // the IncomingReg register in the corresponding predecessor basic block. // 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 + // source path the PHI. MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock(); // Check to make sure we haven't already emitted the copy for this block. @@ -99,7 +128,9 @@ // 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. + // # of entries is usually small, this is not a problem. FIXME: this + // should just check to see if there is already a copy in the bottom of + // this basic block! // bool HaveNotEmitted = true; for (int op = MI->getNumOperands() - 1; op != i; op -= 2) From lattner at cs.uiuc.edu Sun May 11 23:07:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 23:07:00 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/2003-01-15-AlignmentTest.ll Message-ID: <200305120406.XAA22250@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: 2003-01-15-AlignmentTest.ll added (r1.1) --- Log message: Add old test --- Diffs of the changes: Index: llvm/test/Regression/Jello/2003-01-15-AlignmentTest.ll diff -c /dev/null llvm/test/Regression/Jello/2003-01-15-AlignmentTest.ll:1.1 *** /dev/null Sun May 11 23:06:48 2003 --- llvm/test/Regression/Jello/2003-01-15-AlignmentTest.ll Sun May 11 23:06:38 2003 *************** *** 0 **** --- 1,16 ---- + + int %bar(sbyte* %X) { + %P = alloca double ; pointer should be 4 byte aligned! + %R = cast double* %P to int + %A = and int %R, 3 + ret int %A + } + + int %main() { + %SP = alloca sbyte + %X = add uint 0, 0 + alloca sbyte, uint %X + + call int %bar(sbyte* %SP) + ret int %0 + } From lattner at cs.uiuc.edu Sun May 11 23:10:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun May 11 23:10:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/PHIElimination.cpp Message-ID: <200305120409.XAA23435@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: PHIElimination.cpp updated: 1.4 -> 1.5 --- Log message: Fix N^2 algorithm --- Diffs of the changes: Index: llvm/lib/CodeGen/PHIElimination.cpp diff -u llvm/lib/CodeGen/PHIElimination.cpp:1.4 llvm/lib/CodeGen/PHIElimination.cpp:1.5 --- llvm/lib/CodeGen/PHIElimination.cpp:1.4 Sun May 11 22:55:21 2003 +++ llvm/lib/CodeGen/PHIElimination.cpp Sun May 11 23:08:54 2003 @@ -122,41 +122,50 @@ // source path the PHI. MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock(); + // Figure out where to insert the copy, which is at the end of the + // predecessor basic block, but before any terminator/branch + // instructions... + MachineBasicBlock::iterator I = opBlock.end(); + if (I != opBlock.begin()) { // Handle empty blocks + --I; + // must backtrack over ALL the branches in the previous block + while (MII.isTerminatorInstr((*I)->getOpcode()) && + I != opBlock.begin()) + --I; + + // 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.isTerminatorInstr((*I)->getOpcode())) + ++I; + } + // 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 usually small, this is not a problem. FIXME: this - // should just check to see if there is already a copy in the bottom of - // this basic block! + // If we emitted a copy for this basic block already, it will be right + // where we want to insert one now. Just check for a definition of the + // register we are interested in! // bool HaveNotEmitted = true; - for (int op = MI->getNumOperands() - 1; op != i; op -= 2) - if (&opBlock == MI->getOperand(op).getMachineBasicBlock()) { - HaveNotEmitted = false; - break; + + if (I != opBlock.begin()) { + MachineInstr *PrevInst = *(I-1); + for (unsigned i = 0, e = PrevInst->getNumOperands(); i != e; ++i) { + MachineOperand &MO = PrevInst->getOperand(i); + if (MO.isVirtualRegister() && MO.getReg() == IncomingReg) + if (MO.opIsDef() || MO.opIsDefAndUse()) { + HaveNotEmitted = false; + break; + } } + } if (HaveNotEmitted) { - MachineBasicBlock::iterator I = opBlock.end(); - if (I != opBlock.begin()) { // Handle empty blocks - --I; - // must backtrack over ALL the branches in the previous block - while (MII.isTerminatorInstr((*I)->getOpcode()) && - I != opBlock.begin()) - --I; - - // 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.isTerminatorInstr((*I)->getOpcode())) - ++I; - } - - assert(opVal.isVirtualRegister() && - "Machine PHI Operands must all be virtual registers!"); - RegInfo->copyRegToReg(opBlock, I, IncomingReg, opVal.getReg(), RC); + assert(opVal.isVirtualRegister() && + "Machine PHI Operands must all be virtual registers!"); + RegInfo->copyRegToReg(opBlock, I, IncomingReg, opVal.getReg(), RC); } }