[llvm-commits] [llvm] r123310 - in /llvm/trunk: lib/Target/Sparc/SparcISelLowering.cpp lib/Target/Sparc/SparcISelLowering.h lib/Target/Sparc/SparcInstrInfo.td test/CodeGen/SPARC/2011-01-11-FrameAddr.ll

Venkatraman Govindaraju venkatra at cs.wisc.edu
Tue Jan 11 21:08:36 PST 2011


Author: venkatra
Date: Tue Jan 11 23:08:36 2011
New Revision: 123310

URL: http://llvm.org/viewvc/llvm-project?rev=123310&view=rev
Log:
Implement RETURNADDR and FRAMEADDR lowering in SPARC backend.

Added:
    llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
Modified:
    llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
    llvm/trunk/lib/Target/Sparc/SparcISelLowering.h
    llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td

Modified: llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp?rev=123310&r1=123309&r2=123310&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp Tue Jan 11 23:08:36 2011
@@ -743,6 +743,8 @@
   case SPISD::ITOF:       return "SPISD::ITOF";
   case SPISD::CALL:       return "SPISD::CALL";
   case SPISD::RET_FLAG:   return "SPISD::RET_FLAG";
+  case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";
+  case SPISD::FLUSH:      return "SPISD::FLUSH";
   }
 }
 
@@ -990,13 +992,82 @@
 }
 
 
+static SDValue getFLUSH(SDValue Op, SelectionDAG &DAG) {
+  DebugLoc dl = Op.getDebugLoc();
+  SDValue Chain = DAG.getNode(SPISD::FLUSH,
+                              dl, MVT::Other, DAG.getEntryNode());
+  return Chain;
+}
+
+static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) {
+  MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
+  MFI->setFrameAddressIsTaken(true);
+
+  EVT VT = Op.getValueType();
+  DebugLoc dl = Op.getDebugLoc();
+  unsigned FrameReg = SP::I6;
+
+  uint64_t depth = Op.getConstantOperandVal(0);
+
+  SDValue FrameAddr;
+  if (depth == 0) 
+    FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
+  else {
+    // flush first to make sure the windowed registers' values are in stack
+    SDValue Chain = getFLUSH(Op, DAG);
+    FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
+    
+    for (uint64_t i = 0; i != depth; ++i) {
+      SDValue Ptr = DAG.getNode(ISD::ADD, 
+                                dl, MVT::i32,
+                                FrameAddr, DAG.getIntPtrConstant(56));
+      FrameAddr = DAG.getLoad(MVT::i32, dl, 
+                              Chain, 
+                              Ptr,
+                              MachinePointerInfo(), false, false, 0);
+    }
+  }
+  return FrameAddr;
+}
+
+static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) {
+  MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
+  MFI->setReturnAddressIsTaken(true);
+
+  EVT VT = Op.getValueType();
+  DebugLoc dl = Op.getDebugLoc();
+  unsigned RetReg = SP::I7;
+
+  uint64_t depth = Op.getConstantOperandVal(0);
+
+  SDValue RetAddr;
+  if (depth == 0) 
+    RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT);
+  else {
+    // flush first to make sure the windowed registers' values are in stack
+    SDValue Chain = getFLUSH(Op, DAG);
+    RetAddr = DAG.getCopyFromReg(Chain, dl, SP::I6, VT);
+    
+    for (uint64_t i = 0; i != depth; ++i) {
+      SDValue Ptr = DAG.getNode(ISD::ADD, 
+                                dl, MVT::i32,
+                                RetAddr, 
+                                DAG.getIntPtrConstant((i == depth-1)?60:56));
+      RetAddr = DAG.getLoad(MVT::i32, dl, 
+                            Chain, 
+                            Ptr,
+                            MachinePointerInfo(), false, false, 0);
+    }
+  }
+  return RetAddr;
+}
+
 SDValue SparcTargetLowering::
 LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   switch (Op.getOpcode()) {
   default: llvm_unreachable("Should not custom lower this!");
-  // Frame & Return address.  Currently unimplemented
-  case ISD::RETURNADDR: return SDValue();
-  case ISD::FRAMEADDR:  return SDValue();
+  case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
+  case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
   case ISD::GlobalTLSAddress:
     llvm_unreachable("TLS not implemented for Sparc.");
   case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);

Modified: llvm/trunk/lib/Target/Sparc/SparcISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelLowering.h?rev=123310&r1=123309&r2=123310&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcISelLowering.h (original)
+++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.h Tue Jan 11 23:08:36 2011
@@ -36,7 +36,8 @@
 
       CALL,        // A call instruction.
       RET_FLAG,    // Return with a flag operand.
-      GLOBAL_BASE_REG // Global base reg for PIC
+      GLOBAL_BASE_REG, // Global base reg for PIC
+      FLUSH        // FLUSH registers to stack
     };
   }
 

Modified: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td?rev=123310&r1=123309&r2=123310&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td (original)
+++ llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td Tue Jan 11 23:08:36 2011
@@ -127,6 +127,9 @@
 def retflag       : SDNode<"SPISD::RET_FLAG", SDTNone,
                            [SDNPHasChain, SDNPOptInGlue]>;
 
+def flush         : SDNode<"SPISD::FLUSH", SDTNone,
+                           [SDNPHasChain]>;
+
 def getPCX        : Operand<i32> {
   let PrintMethod = "printGetPCX";
 }  
@@ -218,6 +221,12 @@
                             [(callseq_end timm:$amt1, timm:$amt2)]>;
 }
 
+let hasSideEffects = 1, mayStore = 1 in
+  let rs2 = 0 in
+    def FLUSH : F3_1<0b10, 0b101011, (outs), (ins),
+                     "flushw",
+                     [(flush)]>;
+
 // FpMOVD/FpNEGD/FpABSD - These are lowered to single-precision ops by the 
 // fpmover pass.
 let Predicates = [HasNoV9] in {  // Only emit these in V8 mode.

Added: llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll?rev=123310&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll (added)
+++ llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll Tue Jan 11 23:08:36 2011
@@ -0,0 +1,46 @@
+;RUN: llc -march=sparc < %s | FileCheck %s
+
+
+define i8* @frameaddr() nounwind readnone {
+entry:
+;CHECK: frameaddr
+;CHECK: or %g0, %fp, {{.+}}
+  %0 = tail call i8* @llvm.frameaddress(i32 0)
+  ret i8* %0
+}
+
+define i8* @frameaddr2() nounwind readnone {
+entry:
+;CHECK: frameaddr2
+;CHECK: flushw
+;CHECK: ld [%fp+56], {{.+}}
+;CHECK: ld [{{.+}}+56], {{.+}}
+;CHECK: ld [{{.+}}+56], {{.+}}
+  %0 = tail call i8* @llvm.frameaddress(i32 3)
+  ret i8* %0
+}
+
+declare i8* @llvm.frameaddress(i32) nounwind readnone
+
+
+
+define i8* @retaddr() nounwind readnone {
+entry:
+;CHECK: retaddr
+;CHECK: or %g0, %i7, {{.+}}
+  %0 = tail call i8* @llvm.returnaddress(i32 0)
+  ret i8* %0
+}
+
+define i8* @retaddr2() nounwind readnone {
+entry:
+;CHECK: retaddr2
+;CHECK: flushw
+;CHECK: ld [%fp+56], {{.+}}
+;CHECK: ld [{{.+}}+56], {{.+}}
+;CHECK: ld [{{.+}}+60], {{.+}}
+  %0 = tail call i8* @llvm.returnaddress(i32 3)
+  ret i8* %0
+}
+
+declare i8* @llvm.returnaddress(i32) nounwind readnone





More information about the llvm-commits mailing list