llvm.org GIT mirror llvm / 3484da9
Only pass 'returned' to target-specific lowering code when the value of entire register is guaranteed to be preserved. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180825 91177308-0d34-0410-b5e6-96231b3b80d8 Stephen Lin 7 years ago
4 changed file(s) with 220 addition(s) and 92 deletion(s). Raw diff Collapse all Expand all
268268 i != e; ++i) {
269269 unsigned attrInd = i - I->op_begin() + 1;
270270 if (cast(I)->paramHasAttr(attrInd, Attribute::Returned) &&
271 !cast(I)->paramHasAttr(attrInd, Attribute::ZExt) &&
272 !cast(I)->paramHasAttr(attrInd, Attribute::SExt) &&
273271 isNoopBitcast((*i)->getType(), I->getType(), TLI)) {
274272 NoopInput = *i;
275273 break;
283281 i != e; ++i) {
284282 unsigned attrInd = i - I->op_begin() + 1;
285283 if (cast(I)->paramHasAttr(attrInd, Attribute::Returned) &&
286 !cast(I)->paramHasAttr(attrInd, Attribute::ZExt) &&
287 !cast(I)->paramHasAttr(attrInd, Attribute::SExt) &&
288284 isNoopBitcast((*i)->getType(), I->getType(), TLI)) {
289285 NoopInput = *i;
290286 break;
63976397 /// migrated to using LowerCall, this hook should be integrated into SDISel.
63986398 std::pair
63996399 TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
6400 // Handle the incoming return values from the call.
6401 CLI.Ins.clear();
6402 SmallVector RetTys;
6403 ComputeValueVTs(*this, CLI.RetTy, RetTys);
6404 for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
6405 EVT VT = RetTys[I];
6406 MVT RegisterVT = getRegisterType(CLI.RetTy->getContext(), VT);
6407 unsigned NumRegs = getNumRegisters(CLI.RetTy->getContext(), VT);
6408 for (unsigned i = 0; i != NumRegs; ++i) {
6409 ISD::InputArg MyFlags;
6410 MyFlags.VT = RegisterVT;
6411 MyFlags.Used = CLI.IsReturnValueUsed;
6412 if (CLI.RetSExt)
6413 MyFlags.Flags.setSExt();
6414 if (CLI.RetZExt)
6415 MyFlags.Flags.setZExt();
6416 if (CLI.IsInReg)
6417 MyFlags.Flags.setInReg();
6418 CLI.Ins.push_back(MyFlags);
6419 }
6420 }
6421
64006422 // Handle all of the outgoing arguments.
64016423 CLI.Outs.clear();
64026424 CLI.OutVals.clear();
64386460 }
64396461 if (Args[i].isNest)
64406462 Flags.setNest();
6441 if (Args[i].isReturned)
6442 Flags.setReturned();
64436463 Flags.setOrigAlign(OriginalAlignment);
64446464
64456465 MVT PartVT = getRegisterType(CLI.RetTy->getContext(), VT);
64516471 ExtendKind = ISD::SIGN_EXTEND;
64526472 else if (Args[i].isZExt)
64536473 ExtendKind = ISD::ZERO_EXTEND;
6474
6475 // Conservatively only handle 'returned' on non-vectors for now
6476 if (Args[i].isReturned && !Op.getValueType().isVector()) {
6477 assert(CLI.RetTy == Args[i].Ty && RetTys.size() == NumValues &&
6478 "unexpected use of 'returned'");
6479 // Before passing 'returned' to the target lowering code, ensure that
6480 // either the register MVT and the actual EVT are the same size or that
6481 // the return value and argument are extended in the same way; in these
6482 // cases it's safe to pass the argument register value unchanged as the
6483 // return register value (although it's at the target's option whether
6484 // to do so)
6485 // TODO: allow code generation to take advantage of partially preserved
6486 // registers rather than clobbering the entire register when the
6487 // parameter extension method is not compatible with the return
6488 // extension method
6489 if ((NumParts * PartVT.getSizeInBits() == VT.getSizeInBits()) ||
6490 (ExtendKind != ISD::ANY_EXTEND &&
6491 CLI.RetSExt == Args[i].isSExt && CLI.RetZExt == Args[i].isZExt))
6492 Flags.setReturned();
6493 }
64546494
64556495 getCopyToParts(CLI.DAG, CLI.DL, Op, &Parts[0], NumParts,
64566496 PartVT, CLI.CS ? CLI.CS->getInstruction() : 0, ExtendKind);
64686508 CLI.Outs.push_back(MyFlags);
64696509 CLI.OutVals.push_back(Parts[j]);
64706510 }
6471 }
6472 }
6473
6474 // Handle the incoming return values from the call.
6475 CLI.Ins.clear();
6476 SmallVector RetTys;
6477 ComputeValueVTs(*this, CLI.RetTy, RetTys);
6478 for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
6479 EVT VT = RetTys[I];
6480 MVT RegisterVT = getRegisterType(CLI.RetTy->getContext(), VT);
6481 unsigned NumRegs = getNumRegisters(CLI.RetTy->getContext(), VT);
6482 for (unsigned i = 0; i != NumRegs; ++i) {
6483 ISD::InputArg MyFlags;
6484 MyFlags.VT = RegisterVT;
6485 MyFlags.Used = CLI.IsReturnValueUsed;
6486 if (CLI.RetSExt)
6487 MyFlags.Flags.setSExt();
6488 if (CLI.RetZExt)
6489 MyFlags.Flags.setZExt();
6490 if (CLI.IsInReg)
6491 MyFlags.Flags.setInReg();
6492 CLI.Ins.push_back(MyFlags);
64936511 }
64946512 }
64956513
0 ; RUN: llc < %s -mtriple=armv6-linux-gnueabi -arm-tail-calls | FileCheck %s -check-prefix=CHECKELF
1 ; RUN: llc < %s -mtriple=thumbv7-apple-ios -arm-tail-calls | FileCheck %s -check-prefix=CHECKT2D
2
3 declare i16 @identity16(i16 returned %x)
4 declare i32 @identity32(i32 returned %x)
5 declare zeroext i16 @retzext16(i16 returned %x)
6 declare i16 @paramzext16(i16 zeroext returned %x)
7 declare zeroext i16 @bothzext16(i16 zeroext returned %x)
8
9 ; The zeroext param attribute below is meant to have no effect
10 define i16 @test_identity(i16 zeroext %x) {
11 entry:
12 ; CHECKELF: test_identity:
13 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
14 ; CHECKELF: bl identity16
15 ; CHECKELF: uxth r0, r0
16 ; CHECKELF: bl identity32
17 ; CHECKELF: mov r0, [[SAVEX]]
18 ; CHECKT2D: test_identity:
19 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
20 ; CHECKT2D: blx _identity16
21 ; CHECKT2D: uxth r0, r0
22 ; CHECKT2D: blx _identity32
23 ; CHECKT2D: mov r0, [[SAVEX]]
24 %call = tail call i16 @identity16(i16 %x)
25 %b = zext i16 %call to i32
26 %call2 = tail call i32 @identity32(i32 %b)
27 ret i16 %x
28 }
29
30 ; FIXME: This ought not to require register saving but currently does because
31 ; x is not considered equal to %call (see SelectionDAGBuilder.cpp)
32 define i16 @test_matched_ret(i16 %x) {
33 entry:
34 ; CHECKELF: test_matched_ret:
35
36 ; This shouldn't be required
37 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
38
39 ; CHECKELF: bl retzext16
40 ; CHECKELF-NOT: uxth r0, {{r[0-9]+}}
41 ; CHECKELF: bl identity32
42
43 ; This shouldn't be required
44 ; CHECKELF: mov r0, [[SAVEX]]
45
46 ; CHECKT2D: test_matched_ret:
47
48 ; This shouldn't be required
49 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
50
51 ; CHECKT2D: blx _retzext16
52 ; CHECKT2D-NOT: uxth r0, {{r[0-9]+}}
53 ; CHECKT2D: blx _identity32
54
55 ; This shouldn't be required
56 ; CHECKT2D: mov r0, [[SAVEX]]
57
58 %call = tail call i16 @retzext16(i16 %x)
59 %b = zext i16 %call to i32
60 %call2 = tail call i32 @identity32(i32 %b)
61 ret i16 %x
62 }
63
64 define i16 @test_mismatched_ret(i16 %x) {
65 entry:
66 ; CHECKELF: test_mismatched_ret:
67 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
68 ; CHECKELF: bl retzext16
69 ; CHECKELF: sxth r0, {{r[0-9]+}}
70 ; CHECKELF: bl identity32
71 ; CHECKELF: mov r0, [[SAVEX]]
72 ; CHECKT2D: test_mismatched_ret:
73 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
74 ; CHECKT2D: blx _retzext16
75 ; CHECKT2D: sxth r0, {{r[0-9]+}}
76 ; CHECKT2D: blx _identity32
77 ; CHECKT2D: mov r0, [[SAVEX]]
78 %call = tail call i16 @retzext16(i16 %x)
79 %b = sext i16 %call to i32
80 %call2 = tail call i32 @identity32(i32 %b)
81 ret i16 %x
82 }
83
84 define i16 @test_matched_paramext(i16 %x) {
85 entry:
86 ; CHECKELF: test_matched_paramext:
87 ; CHECKELF: uxth r0, r0
88 ; CHECKELF: bl paramzext16
89 ; CHECKELF: uxth r0, r0
90 ; CHECKELF: bl identity32
91 ; CHECKELF: b paramzext16
92 ; CHECKT2D: test_matched_paramext:
93 ; CHECKT2D: uxth r0, r0
94 ; CHECKT2D: blx _paramzext16
95 ; CHECKT2D: uxth r0, r0
96 ; CHECKT2D: blx _identity32
97 ; CHECKT2D: b.w _paramzext16
98 %call = tail call i16 @paramzext16(i16 %x)
99 %b = zext i16 %call to i32
100 %call2 = tail call i32 @identity32(i32 %b)
101 %call3 = tail call i16 @paramzext16(i16 %call)
102 ret i16 %call3
103 }
104
105 ; FIXME: This theoretically ought to optimize to exact same output as the
106 ; version above, but doesn't currently (see SelectionDAGBuilder.cpp)
107 define i16 @test_matched_paramext2(i16 %x) {
108 entry:
109
110 ; Since there doesn't seem to be an unambiguous optimal selection and
111 ; scheduling of uxth and mov instructions below in lieu of the 'returned'
112 ; optimization, don't bother checking: just verify that the calls are made
113 ; in the correct order as a basic sanity check
114
115 ; CHECKELF: test_matched_paramext2:
116 ; CHECKELF: bl paramzext16
117 ; CHECKELF: bl identity32
118 ; CHECKELF: b paramzext16
119 ; CHECKT2D: test_matched_paramext2:
120 ; CHECKT2D: blx _paramzext16
121 ; CHECKT2D: blx _identity32
122 ; CHECKT2D: b.w _paramzext16
123 %call = tail call i16 @paramzext16(i16 %x)
124
125 ; Should make no difference if %x is used below rather than %call, but it does
126 %b = zext i16 %x to i32
127
128 %call2 = tail call i32 @identity32(i32 %b)
129 %call3 = tail call i16 @paramzext16(i16 %call)
130 ret i16 %call3
131 }
132
133 define i16 @test_matched_bothext(i16 %x) {
134 entry:
135 ; CHECKELF: test_matched_bothext:
136 ; CHECKELF: uxth r0, r0
137 ; CHECKELF: bl bothzext16
138 ; CHECKELF-NOT: uxth r0, r0
139
140 ; FIXME: Tail call should be OK here
141 ; CHECKELF: bl identity32
142
143 ; CHECKT2D: test_matched_bothext:
144 ; CHECKT2D: uxth r0, r0
145 ; CHECKT2D: blx _bothzext16
146 ; CHECKT2D-NOT: uxth r0, r0
147
148 ; FIXME: Tail call should be OK here
149 ; CHECKT2D: blx _identity32
150
151 %call = tail call i16 @bothzext16(i16 %x)
152 %b = zext i16 %x to i32
153 %call2 = tail call i32 @identity32(i32 %b)
154 ret i16 %call
155 }
156
157 define i16 @test_mismatched_bothext(i16 %x) {
158 entry:
159 ; CHECKELF: test_mismatched_bothext:
160 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
161 ; CHECKELF: uxth r0, {{r[0-9]+}}
162 ; CHECKELF: bl bothzext16
163 ; CHECKELF: sxth r0, [[SAVEX]]
164 ; CHECKELF: bl identity32
165 ; CHECKELF: mov r0, [[SAVEX]]
166 ; CHECKT2D: test_mismatched_bothext:
167 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
168 ; CHECKT2D: uxth r0, {{r[0-9]+}}
169 ; CHECKT2D: blx _bothzext16
170 ; CHECKT2D: sxth r0, [[SAVEX]]
171 ; CHECKT2D: blx _identity32
172 ; CHECKT2D: mov r0, [[SAVEX]]
173 %call = tail call i16 @bothzext16(i16 %x)
174 %b = sext i16 %x to i32
175 %call2 = tail call i32 @identity32(i32 %b)
176 ret i16 %x
177 }
102102 %call2 = tail call %struct.B* @B_ctor_complete(%struct.B* %b2, i32 %x)
103103 ret %struct.E* %this
104104 }
105
106 declare i16 @identity16(i16 returned %x)
107 declare zeroext i16 @zeroext16(i16 returned %x)
108 declare i32 @identity32(i32 returned %x)
109
110 define i16 @test_identity(i16 %x) {
111 entry:
112 ; CHECKELF: test_identity:
113 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
114 ; CHECKELF: bl identity16
115 ; CHECKELF: uxth r0, [[SAVEX]]
116 ; CHECKELF: bl identity32
117 ; CHECKELF: mov r0, [[SAVEX]]
118 ; CHECKT2D: test_identity:
119 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
120 ; CHECKT2D: blx _identity16
121 ; CHECKT2D: uxth r0, [[SAVEX]]
122 ; CHECKT2D: blx _identity32
123 ; CHECKT2D: mov r0, [[SAVEX]]
124 %call = tail call i16 @identity16(i16 %x)
125 %b = zext i16 %x to i32
126 %call2 = tail call i32 @identity32(i32 %b)
127 ret i16 %call
128 }
129
130 define i16 @test_matched_ext(i16 %x) {
131 entry:
132 ; CHECKELF: test_matched_ext:
133 ; CHECKELF-NOT: mov {{r[0-9]+}}, r0
134 ; CHECKELF: bl zeroext16
135 ; CHECKELF-NOT: uxth r0, {{r[0-9]+}}
136 ; CHECKELF: bl identity32
137 ; CHECKELF-NOT: mov r0, {{r[0-9]+}}
138 ; CHECKT2D: test_matched_ext:
139 ; CHECKT2D-NOT: mov {{r[0-9]+}}, r0
140 ; CHECKT2D: blx _zeroext16
141 ; CHECKT2D-NOT: uxth r0, {{r[0-9]+}}
142 ; CHECKT2D: blx _identity32
143 ; CHECKT2D-NOT: mov r0, {{r[0-9]+}}
144 %call = tail call i16 @zeroext16(i16 %x)
145 %b = zext i16 %call to i32
146 %call2 = tail call i32 @identity32(i32 %b)
147 ret i16 %call
148 }
149
150 define i16 @test_mismatched_ext(i16 %x) {
151 entry:
152 ; CHECKELF: test_mismatched_ext:
153 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
154 ; CHECKELF: bl zeroext16
155 ; CHECKELF: sxth r0, [[SAVEX]]
156 ; CHECKELF: bl identity32
157 ; CHECKELF: mov r0, [[SAVEX]]
158 ; CHECKT2D: test_mismatched_ext:
159 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
160 ; CHECKT2D: blx _zeroext16
161 ; CHECKT2D: sxth r0, [[SAVEX]]
162 ; CHECKT2D: blx _identity32
163 ; CHECKT2D: mov r0, [[SAVEX]]
164 %call = tail call i16 @zeroext16(i16 %x)
165 %b = sext i16 %call to i32
166 %call2 = tail call i32 @identity32(i32 %b)
167 ret i16 %call
168 }