[llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp SparcInstManip.h
Joel Stanley
jstanley at cs.uiuc.edu
Sun May 18 22:01:00 PDT 2003
Changes in directory llvm/lib/Reoptimizer/Inst/lib:
SparcInstManip.cpp updated: 1.14 -> 1.15
SparcInstManip.h updated: 1.13 -> 1.14
---
Log message:
Fixed bug with address copy when the compiler-generated address arithmetic
relies on a value in a local register. The solution is a bit ugly, and a better
one is probably needed.
---
Diffs of the changes:
Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp
diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.14 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.15
--- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.14 Sun May 18 20:35:31 2003
+++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp Sun May 18 22:00:38 2003
@@ -5,9 +5,10 @@
// purpose: Implements the SparcInstManip class as described in SparcInstManip.h
//
// SparcInstManip implements behavior that constructs the contents of "slots" -- regions
-// of memory allocated by a MemoryManager instance that will be branch to at runtime. A
-// phase n slot is written by phase n-1, and is when executed, invokes the appropriate
-// function for phase n.
+// of memory allocated by a MemoryManager instance and/or off of the heap that will be
+// branched to at runtime. A phase n slot is written by phase n-1, and is when executed,
+// invokes the appropriate function for phase n. The notable exception is the last phase,
+// which will end up invoking the proper instrumentation function.
//
// Phase 3 slot:
// +------------------------------------+
@@ -34,23 +35,27 @@
// | 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.
-// +------------------------------------------------------+
-// | alloc spill area/reg save/inst param region on stack |
-// | manually-save clobbered registers |
-// | spill shared registers |
-// | copy GBTElem 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 |
-// +------------------------------------------------------+
+// Phase 5 "jump slot":
+// +---------------------------------------------------+
+// | obtain new stack frame w/ spill region & RA space |
+// | load address of heap slot |
+// | jmpl to heap slot |
+// | branch back to orig code |
+// | restore registers |
+// +---------------------------------------------------+
+//
+//
+// Phase 5 heap slot:
+// +-------------------------------------------------+
+// | spill shared registers (to stack) |
+// | copy GBTElem ptr to param 1 |
+// | copy spill area addr to param 2 |
+// | call phase 5 |
+// | nop |
+// | restore shared registers (from stack) |
+// | return to phase 5 jump slot |
+// | nop |
+// +-------------------------------------------------+
// []
#include <iostream>
@@ -123,7 +128,7 @@
m_outputToInputReg[i] = i;
}
-static unsigned getSPSub(unsigned size)
+static unsigned getSPSub(int size)
{
return MK_ADD_R_I(R_O6, R_O6, -size);
}
@@ -166,15 +171,31 @@
uint64_t slotBase = p4info->getSlot();
uint64_t spillAddr = (uint64_t) getPhase4SpillAddr();
const InstCandidate& cand = p4info->getCandidate();
+
+ // It is possible that the arithmetic used in the load-volatile instruction candidate
+ // uses a local register. If this is the case, we must perform the arithmetic before
+ // actually issuing the save command, because we lose the contents of the local
+ // registers after the save completes. Hence, we make room for one word on the stack
+ // so that we can save the result of the arithmetic.
startCode(snippet);
+ unsigned stkSize = getAligned(STKFRM_MIN + WORD_WIDTH);
+ generateSPSub(stkSize);
+ generateStackStore(REG_0, STKFRM_MIN);
+ generateAddressCopy(cand.front().second, REG_0, false); // REG_0 live to call
generateSave();
+ // REG_0, which was "live to call" at the address copy, is now the corresponding
+ // input register because the save instruction gave us a new window. Transfer the
+ // value in the corresponding input register into REG_0.
+
+ unsigned reg = m_logicalToActualReg[REG_0];
+ m_pCurrSnippet->push_back(MK_MOV_R_R(reg, m_outputToInputReg[reg]));
+
// NB: Pass the value found in the register used by the candidate-load instruction,
// and the p4info ptr to the phase4 function call.
- generateAddressCopy(cand.front().second, REG_0, true); // REG_0 live to call
generateStackStore(REG_0, PARAM_0);
generateSpillShared(spillAddr, REG_1, REG_2);
generateLoad((uint64_t) p4info, REG_1, REG_2); // REG_1 live to call
@@ -182,7 +203,9 @@
generateCall((uint64_t) &phase4, slotBase);
generateRestoreShared(spillAddr, REG_0, REG_1);
- generateBranchAlways(cand.front().first, slotBase, getRestoreInst());
+ generateRestore();
+ generateStackLoad(REG_0, STKFRM_MIN);
+ generateBranchAlways(cand.front().first, slotBase, getSPSub(-stkSize));
endCode();
@@ -208,13 +231,13 @@
{
unsigned sharedSize = WORD_WIDTH * getSharedSize();
- // WORD_WIDTH * 3 belows occurs because we need two words for saving the values of the
- // two scratch registers, and 1 word for saving the return address in the jump slot.
- unsigned stkSize = getAligned(STKFRM_MIN + sharedSize + WORD_WIDTH * 3);
+ // WORD_WIDTH occurs below because we need a word for saving the return address (in
+ // the jump slot) for use in the heap slot.
+ unsigned stkSize = getAligned(STKFRM_MIN + sharedSize + WORD_WIDTH);
DEBUG_MSG(2, "buildSlot(p5) stack offset is " << stkSize << endl);
- unsigned retAddrStkOff = STKFRM_MIN + sharedSize + 2 * WORD_WIDTH;
+ unsigned retAddrStkOff = STKFRM_MIN + sharedSize;
unsigned* heapSlot = buildPhase5HeapSlot(gbte, sharedSize, retAddrStkOff);
DEBUG_MSG(2, "buildPhase5HeapSlot completed\n");
@@ -238,27 +261,17 @@
// +--------------------------------+
// | ret addr for use by heap slot | } WORD_WIDTH
// +--------------------------------+
- // | save area for clobbered regs | } WORD_WIDTH * 2
- // +--------------------------------+
// | spill region for shared regs | } sharedSize
// sp + BIAS + STKFRM_MIN -> +--------------------------------+
//
- generateSPSub(stkSize);
-
- // Save registers REG_{0,7} so we don't have to issue a 'save'
- generateStackStore(REG_0, STKFRM_MIN + sharedSize);
- generateStackStore(REG_7, STKFRM_MIN + sharedSize + WORD_WIDTH);
+ generateSave(stkSize);
// Address of jmpl instruction will be in REG_7 at entry to heapSlot.
// This means that REG_7 is live until its use in heapSlot.
generateLdJmpl((uint64_t) heapSlot, REG_0, REG_7);
- // Restore registers REG_{0,7} so we don't have to issue a 'restore'
- generateStackLoad(REG_0, STKFRM_MIN + sharedSize);
- generateStackLoad(REG_7, STKFRM_MIN + sharedSize + WORD_WIDTH);
-
- generateBranchAlways(instAddr + getInstWidth(), slotBase, getSPSub(-stkSize));
+ generateBranchAlways(instAddr + getInstWidth(), slotBase, getRestoreInst());
endCode();
DEBUG_MSG(2, "buildSlot(p5) completed\n");
@@ -289,14 +302,19 @@
(void) p3;
- return GEN_SAVE_SIZE +
+ return GEN_SPSUB_SIZE +
+ GEN_STKSTORE_SIZE +
getGenAddressCopySize(cand.front().second) +
+ GEN_SAVE_SIZE +
+ GEN_MOV_SIZE +
GEN_STKSTORE_SIZE +
GEN_SPL_SIZE +
GEN_LOAD_SIZE +
GEN_STKSTORE_SIZE +
GEN_CALL_SIZE +
GEN_UNSPL_SIZE +
+ GEN_RESTORE_SIZE +
+ GEN_STKLOAD_SIZE +
GEN_BRANCH_ALWAYS_SIZE;
}
@@ -309,14 +327,8 @@
(void) p4;
return
- GEN_SPSUB_SIZE +
- GEN_STKSTORE_SIZE +
- GEN_STKSTORE_SIZE +
- GEN_STKSTORE_SIZE +
+ GEN_SAVE_SIZE +
GEN_LDJMPL_SIZE +
- GEN_STKLOAD_SIZE +
- GEN_STKLOAD_SIZE +
- GEN_STKLOAD_SIZE +
GEN_BRANCH_ALWAYS_SIZE;
}
@@ -493,9 +505,9 @@
"Unexpected number of instructions in code sequence for SP offset");
}
-// generateSPSub - Generate code to allocate 'size' bytes on the stack
+// generateSPSub - Generate code to decrement %sp by 'size' bytes.
-void SparcInstManip::generateSPSub(unsigned size)
+void SparcInstManip::generateSPSub(int size)
{
assert(m_pCurrSnippet && "Invalid snippet for code generation");
assert(size % STACK_ALIGN == 0 && "SP size is not aligned");
Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h
diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.13 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.14
--- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.13 Sun May 18 20:35:31 2003
+++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h Sun May 18 22:00:38 2003
@@ -70,7 +70,7 @@
void generateCall(uint64_t dest, uint64_t slotBase);
void generateSPOffset(LogicalRegister reg, unsigned offset);
- void generateSPSub(unsigned size);
+ void generateSPSub(int size);
void generateJmpl(LogicalRegister useForIndirect,
LogicalRegister returnAddrDest,
@@ -175,6 +175,7 @@
static const unsigned GEN_SPOFFSET_SIZE = 1;
static const unsigned GEN_JMPL_SIZE = 2;
static const unsigned GEN_LDJMPL_SIZE = GEN_LOAD_SIZE + GEN_JMPL_SIZE;
+ static const unsigned GEN_MOV_SIZE = 1;
};
unsigned SparcInstManip::getBranchAlways(uint64_t dest, uint64_t pc, bool annul) const
More information about the llvm-commits
mailing list