1263320SdimPull in r198480 from upstream llvm trunk (by Venkatraman Govindaraju):
2263320Sdim
3263320Sdim  [SparcV9]: Implement RETURNADDR and FRAMEADDR lowering in SPARC64. 
4263320Sdim
5269012SemasteIntroduced here: http://svnweb.freebsd.org/changeset/base/262261
6263320Sdim
7263320SdimIndex: lib/Target/Sparc/SparcISelLowering.cpp
8263320Sdim===================================================================
9263320Sdim--- lib/Target/Sparc/SparcISelLowering.cpp
10263320Sdim+++ lib/Target/Sparc/SparcISelLowering.cpp
11263320Sdim@@ -2415,7 +2415,8 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG
12263320Sdim   return Chain;
13263320Sdim }
14263320Sdim 
15263320Sdim-static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) {
16263320Sdim+static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
17263320Sdim+                            const SparcSubtarget *Subtarget) {
18263320Sdim   MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
19263320Sdim   MFI->setFrameAddressIsTaken(true);
20263320Sdim 
21263320Sdim@@ -2422,32 +2423,49 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG
22263320Sdim   EVT VT = Op.getValueType();
23263320Sdim   SDLoc dl(Op);
24263320Sdim   unsigned FrameReg = SP::I6;
25263320Sdim+  unsigned stackBias = Subtarget->getStackPointerBias();
26263320Sdim 
27263320Sdim-  uint64_t depth = Op.getConstantOperandVal(0);
28263320Sdim+  SDValue FrameAddr;
29263320Sdim 
30263320Sdim-  SDValue FrameAddr;
31263320Sdim-  if (depth == 0)
32263320Sdim+  if (depth == 0) {
33263320Sdim     FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
34263320Sdim-  else {
35263320Sdim-    // flush first to make sure the windowed registers' values are in stack
36263320Sdim-    SDValue Chain = getFLUSHW(Op, DAG);
37263320Sdim-    FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
38263320Sdim+    if (Subtarget->is64Bit())
39263320Sdim+      FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
40263320Sdim+                              DAG.getIntPtrConstant(stackBias));
41263320Sdim+    return FrameAddr;
42263320Sdim+  }
43263320Sdim 
44263320Sdim-    for (uint64_t i = 0; i != depth; ++i) {
45263320Sdim-      SDValue Ptr = DAG.getNode(ISD::ADD,
46263320Sdim-                                dl, MVT::i32,
47263320Sdim-                                FrameAddr, DAG.getIntPtrConstant(56));
48263320Sdim-      FrameAddr = DAG.getLoad(MVT::i32, dl,
49263320Sdim-                              Chain,
50263320Sdim-                              Ptr,
51263320Sdim-                              MachinePointerInfo(), false, false, false, 0);
52263320Sdim-    }
53263320Sdim+  // flush first to make sure the windowed registers' values are in stack
54263320Sdim+  SDValue Chain = getFLUSHW(Op, DAG);
55263320Sdim+  FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
56263320Sdim+
57263320Sdim+  unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56;
58263320Sdim+
59263320Sdim+  while (depth--) {
60263320Sdim+    SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
61263320Sdim+                              DAG.getIntPtrConstant(Offset));
62263320Sdim+    FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo(),
63263320Sdim+                            false, false, false, 0);
64263320Sdim   }
65263320Sdim+  if (Subtarget->is64Bit())
66263320Sdim+    FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
67263320Sdim+                            DAG.getIntPtrConstant(stackBias));
68263320Sdim   return FrameAddr;
69263320Sdim }
70263320Sdim 
71263320Sdim+
72263320Sdim+static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
73263320Sdim+                              const SparcSubtarget *Subtarget) {
74263320Sdim+
75263320Sdim+  uint64_t depth = Op.getConstantOperandVal(0);
76263320Sdim+
77263320Sdim+  return getFRAMEADDR(depth, Op, DAG, Subtarget);
78263320Sdim+
79263320Sdim+}
80263320Sdim+
81263320Sdim static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
82263320Sdim-                               const SparcTargetLowering &TLI) {
83263320Sdim+                               const SparcTargetLowering &TLI,
84263320Sdim+                               const SparcSubtarget *Subtarget) {
85263320Sdim   MachineFunction &MF = DAG.getMachineFunction();
86263320Sdim   MachineFrameInfo *MFI = MF.getFrameInfo();
87263320Sdim   MFI->setReturnAddressIsTaken(true);
88263320Sdim@@ -2461,25 +2479,20 @@ static SDValue LowerRETURNADDR(SDValue Op, Selecti
89263320Sdim     unsigned RetReg = MF.addLiveIn(SP::I7,
90263320Sdim                                    TLI.getRegClassFor(TLI.getPointerTy()));
91263320Sdim     RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT);
92263320Sdim-  } else {
93263320Sdim-    // Need frame address to find return address of the caller.
94263320Sdim-    MFI->setFrameAddressIsTaken(true);
95263320Sdim+    return RetAddr;
96263320Sdim+  }
97263320Sdim 
98263320Sdim-    // flush first to make sure the windowed registers' values are in stack
99263320Sdim-    SDValue Chain = getFLUSHW(Op, DAG);
100263320Sdim-    RetAddr = DAG.getCopyFromReg(Chain, dl, SP::I6, VT);
101263320Sdim+  // Need frame address to find return address of the caller.
102263320Sdim+  SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget);
103263320Sdim 
104263320Sdim-    for (uint64_t i = 0; i != depth; ++i) {
105263320Sdim-      SDValue Ptr = DAG.getNode(ISD::ADD,
106263320Sdim-                                dl, MVT::i32,
107263320Sdim-                                RetAddr,
108263320Sdim-                                DAG.getIntPtrConstant((i == depth-1)?60:56));
109263320Sdim-      RetAddr = DAG.getLoad(MVT::i32, dl,
110263320Sdim-                            Chain,
111263320Sdim-                            Ptr,
112263320Sdim-                            MachinePointerInfo(), false, false, false, 0);
113263320Sdim-    }
114263320Sdim-  }
115263320Sdim+  unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60;
116263320Sdim+  SDValue Ptr = DAG.getNode(ISD::ADD,
117263320Sdim+                            dl, VT,
118263320Sdim+                            FrameAddr,
119263320Sdim+                            DAG.getIntPtrConstant(Offset));
120263320Sdim+  RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr,
121263320Sdim+                        MachinePointerInfo(), false, false, false, 0);
122263320Sdim+
123263320Sdim   return RetAddr;
124263320Sdim }
125263320Sdim 
126263320Sdim@@ -2763,8 +2776,10 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons
127263320Sdim   switch (Op.getOpcode()) {
128263320Sdim   default: llvm_unreachable("Should not custom lower this!");
129263320Sdim 
130263320Sdim-  case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG, *this);
131263320Sdim-  case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
132263320Sdim+  case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG, *this,
133263320Sdim+                                                       Subtarget);
134263320Sdim+  case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG,
135263320Sdim+                                                      Subtarget);
136263320Sdim   case ISD::GlobalTLSAddress:   return LowerGlobalTLSAddress(Op, DAG);
137263320Sdim   case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);
138263320Sdim   case ISD::BlockAddress:       return LowerBlockAddress(Op, DAG);
139263320SdimIndex: test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
140263320Sdim===================================================================
141263320Sdim--- test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
142263320Sdim+++ test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
143263320Sdim@@ -2,6 +2,7 @@
144263320Sdim ;RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9
145263320Sdim ;RUN: llc -march=sparc -regalloc=basic < %s | FileCheck %s -check-prefix=V8
146263320Sdim ;RUN: llc -march=sparc -regalloc=basic -mattr=v9 < %s | FileCheck %s -check-prefix=V9
147263320Sdim+;RUN: llc -march=sparcv9  < %s | FileCheck %s -check-prefix=SPARC64
148263320Sdim 
149263320Sdim 
150263320Sdim define i8* @frameaddr() nounwind readnone {
151263320Sdim@@ -15,6 +16,13 @@ entry:
152263320Sdim ;V9: save %sp, -96, %sp
153263320Sdim ;V9: jmp %i7+8
154263320Sdim ;V9: restore %g0, %fp, %o0
155263320Sdim+
156263320Sdim+;SPARC64-LABEL: frameaddr
157263320Sdim+;SPARC64:       save %sp, -128, %sp
158263320Sdim+;SPARC64:       add  %fp, 2047, %i0
159263320Sdim+;SPARC64:       jmp %i7+8
160263320Sdim+;SPARC64:       restore %g0, %g0, %g0
161263320Sdim+
162263320Sdim   %0 = tail call i8* @llvm.frameaddress(i32 0)
163263320Sdim   ret i8* %0
164263320Sdim }
165263320Sdim@@ -32,6 +40,14 @@ entry:
166263320Sdim ;V9: ld [%fp+56], {{.+}}
167263320Sdim ;V9: ld [{{.+}}+56], {{.+}}
168263320Sdim ;V9: ld [{{.+}}+56], {{.+}}
169263320Sdim+
170263320Sdim+;SPARC64-LABEL: frameaddr2
171263320Sdim+;SPARC64: flushw
172263320Sdim+;SPARC64: ldx [%fp+2159],     %[[R0:[goli][0-7]]]
173263320Sdim+;SPARC64: ldx [%[[R0]]+2159], %[[R1:[goli][0-7]]]
174263320Sdim+;SPARC64: ldx [%[[R1]]+2159], %[[R2:[goli][0-7]]]
175263320Sdim+;SPARC64: add %[[R2]], 2047, {{.+}}
176263320Sdim+
177263320Sdim   %0 = tail call i8* @llvm.frameaddress(i32 3)
178263320Sdim   ret i8* %0
179263320Sdim }
180263320Sdim@@ -48,6 +64,9 @@ entry:
181263320Sdim ;V9-LABEL: retaddr:
182263320Sdim ;V9: or %g0, %o7, {{.+}}
183263320Sdim 
184263320Sdim+;SPARC64-LABEL: retaddr
185263320Sdim+;SPARC64:       or %g0, %o7, {{.+}}
186263320Sdim+
187263320Sdim   %0 = tail call i8* @llvm.returnaddress(i32 0)
188263320Sdim   ret i8* %0
189263320Sdim }
190263320Sdim@@ -66,18 +85,12 @@ entry:
191263320Sdim ;V9: ld [{{.+}}+56], {{.+}}
192263320Sdim ;V9: ld [{{.+}}+60], {{.+}}
193263320Sdim 
194263320Sdim-;V8LEAF-LABEL: retaddr2:
195263320Sdim-;V8LEAF: ta 3
196263320Sdim-;V8LEAF: ld [%fp+56], %[[R:[goli][0-7]]]
197263320Sdim-;V8LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]]
198263320Sdim-;V8LEAF: ld [%[[R1]]+60], {{.+}}
199263320Sdim+;SPARC64-LABEL: retaddr2
200263320Sdim+;SPARC64:       flushw
201263320Sdim+;SPARC64: ldx [%fp+2159],     %[[R0:[goli][0-7]]]
202263320Sdim+;SPARC64: ldx [%[[R0]]+2159], %[[R1:[goli][0-7]]]
203263320Sdim+;SPARC64: ldx [%[[R1]]+2167], {{.+}}
204263320Sdim 
205263320Sdim-;V9LEAF-LABEL: retaddr2:
206263320Sdim-;V9LEAF: flushw
207263320Sdim-;V9LEAF: ld [%fp+56], %[[R:[goli][0-7]]]
208263320Sdim-;V9LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]]
209263320Sdim-;V9LEAF: ld [%[[R1]]+60], {{.+}}
210263320Sdim-
211263320Sdim   %0 = tail call i8* @llvm.returnaddress(i32 3)
212263320Sdim   ret i8* %0
213263320Sdim }
214