/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/ARM/ARMCallingConv.h
Line | Count | Source (jump to first uncovered line) |
1 | | //=== ARMCallingConv.h - ARM Custom Calling Convention Routines -*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file contains the custom routines for the ARM Calling Convention that |
10 | | // aren't done by tablegen. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef LLVM_LIB_TARGET_ARM_ARMCALLINGCONV_H |
15 | | #define LLVM_LIB_TARGET_ARM_ARMCALLINGCONV_H |
16 | | |
17 | | #include "ARM.h" |
18 | | #include "ARMBaseInstrInfo.h" |
19 | | #include "ARMSubtarget.h" |
20 | | #include "llvm/CodeGen/CallingConvLower.h" |
21 | | #include "llvm/CodeGen/TargetInstrInfo.h" |
22 | | #include "llvm/IR/CallingConv.h" |
23 | | |
24 | | namespace llvm { |
25 | | |
26 | | // APCS f64 is in register pairs, possibly split to stack |
27 | | static bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
28 | | CCValAssign::LocInfo &LocInfo, |
29 | 1.15k | CCState &State, bool CanFail) { |
30 | 1.15k | static const MCPhysReg RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; |
31 | 1.15k | |
32 | 1.15k | // Try to get the first register. |
33 | 1.15k | if (unsigned Reg = State.AllocateReg(RegList)) |
34 | 650 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); |
35 | 503 | else { |
36 | 503 | // For the 2nd half of a v2f64, do not fail. |
37 | 503 | if (CanFail) |
38 | 498 | return false; |
39 | 5 | |
40 | 5 | // Put the whole thing on the stack. |
41 | 5 | State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, |
42 | 5 | State.AllocateStack(8, 4), |
43 | 5 | LocVT, LocInfo)); |
44 | 5 | return true; |
45 | 5 | } |
46 | 650 | |
47 | 650 | // Try to get the second register. |
48 | 650 | if (unsigned Reg = State.AllocateReg(RegList)) |
49 | 610 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); |
50 | 40 | else |
51 | 40 | State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, |
52 | 40 | State.AllocateStack(4, 4), |
53 | 40 | LocVT, LocInfo)); |
54 | 650 | return true; |
55 | 650 | } ARMFastISel.cpp:llvm::f64AssignAPCS(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::CCState&, bool) Line | Count | Source | 29 | 424 | CCState &State, bool CanFail) { | 30 | 424 | static const MCPhysReg RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; | 31 | 424 | | 32 | 424 | // Try to get the first register. | 33 | 424 | if (unsigned Reg = State.AllocateReg(RegList)) | 34 | 5 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | 35 | 419 | else { | 36 | 419 | // For the 2nd half of a v2f64, do not fail. | 37 | 419 | if (CanFail) | 38 | 419 | return false; | 39 | 0 | | 40 | 0 | // Put the whole thing on the stack. | 41 | 0 | State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, | 42 | 0 | State.AllocateStack(8, 4), | 43 | 0 | LocVT, LocInfo)); | 44 | 0 | return true; | 45 | 0 | } | 46 | 5 | | 47 | 5 | // Try to get the second register. | 48 | 5 | if (unsigned Reg = State.AllocateReg(RegList)) | 49 | 4 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | 50 | 1 | else | 51 | 1 | State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, | 52 | 1 | State.AllocateStack(4, 4), | 53 | 1 | LocVT, LocInfo)); | 54 | 5 | return true; | 55 | 5 | } |
ARMISelLowering.cpp:llvm::f64AssignAPCS(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::CCState&, bool) Line | Count | Source | 29 | 729 | CCState &State, bool CanFail) { | 30 | 729 | static const MCPhysReg RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; | 31 | 729 | | 32 | 729 | // Try to get the first register. | 33 | 729 | if (unsigned Reg = State.AllocateReg(RegList)) | 34 | 645 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | 35 | 84 | else { | 36 | 84 | // For the 2nd half of a v2f64, do not fail. | 37 | 84 | if (CanFail) | 38 | 79 | return false; | 39 | 5 | | 40 | 5 | // Put the whole thing on the stack. | 41 | 5 | State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, | 42 | 5 | State.AllocateStack(8, 4), | 43 | 5 | LocVT, LocInfo)); | 44 | 5 | return true; | 45 | 5 | } | 46 | 645 | | 47 | 645 | // Try to get the second register. | 48 | 645 | if (unsigned Reg = State.AllocateReg(RegList)) | 49 | 606 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | 50 | 39 | else | 51 | 39 | State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, | 52 | 39 | State.AllocateStack(4, 4), | 53 | 39 | LocVT, LocInfo)); | 54 | 645 | return true; | 55 | 645 | } |
|
56 | | |
57 | | static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
58 | | CCValAssign::LocInfo &LocInfo, |
59 | | ISD::ArgFlagsTy &ArgFlags, |
60 | 1.06k | CCState &State) { |
61 | 1.06k | if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) |
62 | 498 | return false; |
63 | 571 | if (LocVT == MVT::v2f64 && |
64 | 571 | !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)84 ) |
65 | 0 | return false; |
66 | 571 | return true; // we handled it |
67 | 571 | } ARMFastISel.cpp:llvm::CC_ARM_APCS_Custom_f64(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) Line | Count | Source | 60 | 422 | CCState &State) { | 61 | 422 | if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) | 62 | 419 | return false; | 63 | 3 | if (LocVT == MVT::v2f64 && | 64 | 3 | !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)2 ) | 65 | 0 | return false; | 66 | 3 | return true; // we handled it | 67 | 3 | } |
ARMISelLowering.cpp:llvm::CC_ARM_APCS_Custom_f64(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) Line | Count | Source | 60 | 647 | CCState &State) { | 61 | 647 | if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) | 62 | 79 | return false; | 63 | 568 | if (LocVT == MVT::v2f64 && | 64 | 568 | !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)82 ) | 65 | 0 | return false; | 66 | 568 | return true; // we handled it | 67 | 568 | } |
|
68 | | |
69 | | // AAPCS f64 is in aligned register pairs |
70 | | static bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
71 | | CCValAssign::LocInfo &LocInfo, |
72 | 1.94k | CCState &State, bool CanFail) { |
73 | 1.94k | static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 }; |
74 | 1.94k | static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 }; |
75 | 1.94k | static const MCPhysReg ShadowRegList[] = { ARM::R0, ARM::R1 }; |
76 | 1.94k | static const MCPhysReg GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; |
77 | 1.94k | |
78 | 1.94k | unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList); |
79 | 1.94k | if (Reg == 0) { |
80 | 428 | |
81 | 428 | // If we had R3 unallocated only, now we still must to waste it. |
82 | 428 | Reg = State.AllocateReg(GPRArgRegs); |
83 | 428 | assert((!Reg || Reg == ARM::R3) && "Wrong GPRs usage for f64"); |
84 | 428 | |
85 | 428 | // For the 2nd half of a v2f64, do not just fail. |
86 | 428 | if (CanFail) |
87 | 413 | return false; |
88 | 15 | |
89 | 15 | // Put the whole thing on the stack. |
90 | 15 | State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, |
91 | 15 | State.AllocateStack(8, 8), |
92 | 15 | LocVT, LocInfo)); |
93 | 15 | return true; |
94 | 15 | } |
95 | 1.51k | |
96 | 1.51k | unsigned i; |
97 | 2.15k | for (i = 0; i < 2; ++i638 ) |
98 | 2.15k | if (HiRegList[i] == Reg) |
99 | 1.51k | break; |
100 | 1.51k | |
101 | 1.51k | unsigned T = State.AllocateReg(LoRegList[i]); |
102 | 1.51k | (void)T; |
103 | 1.51k | assert(T == LoRegList[i] && "Could not allocate register"); |
104 | 1.51k | |
105 | 1.51k | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); |
106 | 1.51k | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], |
107 | 1.51k | LocVT, LocInfo)); |
108 | 1.51k | return true; |
109 | 1.51k | } ARMFastISel.cpp:llvm::f64AssignAAPCS(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::CCState&, bool) Line | Count | Source | 72 | 4 | CCState &State, bool CanFail) { | 73 | 4 | static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 }; | 74 | 4 | static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 }; | 75 | 4 | static const MCPhysReg ShadowRegList[] = { ARM::R0, ARM::R1 }; | 76 | 4 | static const MCPhysReg GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; | 77 | 4 | | 78 | 4 | unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList); | 79 | 4 | if (Reg == 0) { | 80 | 0 |
| 81 | 0 | // If we had R3 unallocated only, now we still must to waste it. | 82 | 0 | Reg = State.AllocateReg(GPRArgRegs); | 83 | 0 | assert((!Reg || Reg == ARM::R3) && "Wrong GPRs usage for f64"); | 84 | 0 |
| 85 | 0 | // For the 2nd half of a v2f64, do not just fail. | 86 | 0 | if (CanFail) | 87 | 0 | return false; | 88 | 0 | | 89 | 0 | // Put the whole thing on the stack. | 90 | 0 | State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, | 91 | 0 | State.AllocateStack(8, 8), | 92 | 0 | LocVT, LocInfo)); | 93 | 0 | return true; | 94 | 0 | } | 95 | 4 | | 96 | 4 | unsigned i; | 97 | 6 | for (i = 0; i < 2; ++i2 ) | 98 | 6 | if (HiRegList[i] == Reg) | 99 | 4 | break; | 100 | 4 | | 101 | 4 | unsigned T = State.AllocateReg(LoRegList[i]); | 102 | 4 | (void)T; | 103 | 4 | assert(T == LoRegList[i] && "Could not allocate register"); | 104 | 4 | | 105 | 4 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | 106 | 4 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], | 107 | 4 | LocVT, LocInfo)); | 108 | 4 | return true; | 109 | 4 | } |
ARMISelLowering.cpp:llvm::f64AssignAAPCS(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::CCState&, bool) Line | Count | Source | 72 | 1.94k | CCState &State, bool CanFail) { | 73 | 1.94k | static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 }; | 74 | 1.94k | static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 }; | 75 | 1.94k | static const MCPhysReg ShadowRegList[] = { ARM::R0, ARM::R1 }; | 76 | 1.94k | static const MCPhysReg GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; | 77 | 1.94k | | 78 | 1.94k | unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList); | 79 | 1.94k | if (Reg == 0) { | 80 | 428 | | 81 | 428 | // If we had R3 unallocated only, now we still must to waste it. | 82 | 428 | Reg = State.AllocateReg(GPRArgRegs); | 83 | 428 | assert((!Reg || Reg == ARM::R3) && "Wrong GPRs usage for f64"); | 84 | 428 | | 85 | 428 | // For the 2nd half of a v2f64, do not just fail. | 86 | 428 | if (CanFail) | 87 | 413 | return false; | 88 | 15 | | 89 | 15 | // Put the whole thing on the stack. | 90 | 15 | State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, | 91 | 15 | State.AllocateStack(8, 8), | 92 | 15 | LocVT, LocInfo)); | 93 | 15 | return true; | 94 | 15 | } | 95 | 1.51k | | 96 | 1.51k | unsigned i; | 97 | 2.14k | for (i = 0; i < 2; ++i636 ) | 98 | 2.14k | if (HiRegList[i] == Reg) | 99 | 1.51k | break; | 100 | 1.51k | | 101 | 1.51k | unsigned T = State.AllocateReg(LoRegList[i]); | 102 | 1.51k | (void)T; | 103 | 1.51k | assert(T == LoRegList[i] && "Could not allocate register"); | 104 | 1.51k | | 105 | 1.51k | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | 106 | 1.51k | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], | 107 | 1.51k | LocVT, LocInfo)); | 108 | 1.51k | return true; | 109 | 1.51k | } |
|
110 | | |
111 | | static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
112 | | CCValAssign::LocInfo &LocInfo, |
113 | | ISD::ArgFlagsTy &ArgFlags, |
114 | 1.76k | CCState &State) { |
115 | 1.76k | if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) |
116 | 413 | return false; |
117 | 1.34k | if (LocVT == MVT::v2f64 && |
118 | 1.34k | !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)184 ) |
119 | 0 | return false; |
120 | 1.34k | return true; // we handled it |
121 | 1.34k | } ARMFastISel.cpp:llvm::CC_ARM_AAPCS_Custom_f64(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) Line | Count | Source | 114 | 2 | CCState &State) { | 115 | 2 | if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) | 116 | 0 | return false; | 117 | 2 | if (LocVT == MVT::v2f64 && | 118 | 2 | !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) | 119 | 0 | return false; | 120 | 2 | return true; // we handled it | 121 | 2 | } |
ARMISelLowering.cpp:llvm::CC_ARM_AAPCS_Custom_f64(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) Line | Count | Source | 114 | 1.75k | CCState &State) { | 115 | 1.75k | if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) | 116 | 413 | return false; | 117 | 1.34k | if (LocVT == MVT::v2f64 && | 118 | 1.34k | !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)182 ) | 119 | 0 | return false; | 120 | 1.34k | return true; // we handled it | 121 | 1.34k | } |
|
122 | | |
123 | | static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
124 | 6.36k | CCValAssign::LocInfo &LocInfo, CCState &State) { |
125 | 6.36k | static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 }; |
126 | 6.36k | static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 }; |
127 | 6.36k | |
128 | 6.36k | unsigned Reg = State.AllocateReg(HiRegList, LoRegList); |
129 | 6.36k | if (Reg == 0) |
130 | 61 | return false; // we didn't handle it |
131 | 6.30k | |
132 | 6.30k | unsigned i; |
133 | 8.06k | for (i = 0; i < 2; ++i1.76k ) |
134 | 8.06k | if (HiRegList[i] == Reg) |
135 | 6.30k | break; |
136 | 6.30k | |
137 | 6.30k | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); |
138 | 6.30k | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], |
139 | 6.30k | LocVT, LocInfo)); |
140 | 6.30k | return true; |
141 | 6.30k | } ARMFastISel.cpp:llvm::f64RetAssign(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::CCState&) Line | Count | Source | 124 | 14 | CCValAssign::LocInfo &LocInfo, CCState &State) { | 125 | 14 | static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 }; | 126 | 14 | static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 }; | 127 | 14 | | 128 | 14 | unsigned Reg = State.AllocateReg(HiRegList, LoRegList); | 129 | 14 | if (Reg == 0) | 130 | 0 | return false; // we didn't handle it | 131 | 14 | | 132 | 14 | unsigned i; | 133 | 21 | for (i = 0; i < 2; ++i7 ) | 134 | 21 | if (HiRegList[i] == Reg) | 135 | 14 | break; | 136 | 14 | | 137 | 14 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | 138 | 14 | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], | 139 | 14 | LocVT, LocInfo)); | 140 | 14 | return true; | 141 | 14 | } |
ARMISelLowering.cpp:llvm::f64RetAssign(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::CCState&) Line | Count | Source | 124 | 6.34k | CCValAssign::LocInfo &LocInfo, CCState &State) { | 125 | 6.34k | static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 }; | 126 | 6.34k | static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 }; | 127 | 6.34k | | 128 | 6.34k | unsigned Reg = State.AllocateReg(HiRegList, LoRegList); | 129 | 6.34k | if (Reg == 0) | 130 | 61 | return false; // we didn't handle it | 131 | 6.28k | | 132 | 6.28k | unsigned i; | 133 | 8.04k | for (i = 0; i < 2; ++i1.75k ) | 134 | 8.04k | if (HiRegList[i] == Reg) | 135 | 6.28k | break; | 136 | 6.28k | | 137 | 6.28k | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | 138 | 6.28k | State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], | 139 | 6.28k | LocVT, LocInfo)); | 140 | 6.28k | return true; | 141 | 6.28k | } |
|
142 | | |
143 | | static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
144 | | CCValAssign::LocInfo &LocInfo, |
145 | | ISD::ArgFlagsTy &ArgFlags, |
146 | 4.64k | CCState &State) { |
147 | 4.64k | if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) |
148 | 61 | return false; |
149 | 4.58k | if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)1.72k ) |
150 | 0 | return false; |
151 | 4.58k | return true; // we handled it |
152 | 4.58k | } ARMFastISel.cpp:llvm::RetCC_ARM_APCS_Custom_f64(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) Line | Count | Source | 146 | 7 | CCState &State) { | 147 | 7 | if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) | 148 | 0 | return false; | 149 | 7 | if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) | 150 | 0 | return false; | 151 | 7 | return true; // we handled it | 152 | 7 | } |
ARMISelLowering.cpp:llvm::RetCC_ARM_APCS_Custom_f64(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) Line | Count | Source | 146 | 4.63k | CCState &State) { | 147 | 4.63k | if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) | 148 | 61 | return false; | 149 | 4.57k | if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)1.71k ) | 150 | 0 | return false; | 151 | 4.57k | return true; // we handled it | 152 | 4.57k | } |
|
153 | | |
154 | | static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
155 | | CCValAssign::LocInfo &LocInfo, |
156 | | ISD::ArgFlagsTy &ArgFlags, |
157 | 3.98k | CCState &State) { |
158 | 3.98k | return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, |
159 | 3.98k | State); |
160 | 3.98k | } ARMFastISel.cpp:llvm::RetCC_ARM_AAPCS_Custom_f64(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) Line | Count | Source | 157 | 2 | CCState &State) { | 158 | 2 | return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, | 159 | 2 | State); | 160 | 2 | } |
ARMISelLowering.cpp:llvm::RetCC_ARM_AAPCS_Custom_f64(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) Line | Count | Source | 157 | 3.97k | CCState &State) { | 158 | 3.97k | return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, | 159 | 3.97k | State); | 160 | 3.97k | } |
|
161 | | |
162 | | static const MCPhysReg RRegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; |
163 | | |
164 | | static const MCPhysReg SRegList[] = { ARM::S0, ARM::S1, ARM::S2, ARM::S3, |
165 | | ARM::S4, ARM::S5, ARM::S6, ARM::S7, |
166 | | ARM::S8, ARM::S9, ARM::S10, ARM::S11, |
167 | | ARM::S12, ARM::S13, ARM::S14, ARM::S15 }; |
168 | | static const MCPhysReg DRegList[] = { ARM::D0, ARM::D1, ARM::D2, ARM::D3, |
169 | | ARM::D4, ARM::D5, ARM::D6, ARM::D7 }; |
170 | | static const MCPhysReg QRegList[] = { ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3 }; |
171 | | |
172 | | |
173 | | // Allocate part of an AAPCS HFA or HVA. We assume that each member of the HA |
174 | | // has InConsecutiveRegs set, and that the last member also has |
175 | | // InConsecutiveRegsLast set. We must process all members of the HA before |
176 | | // we can allocate it, as we need to know the total number of registers that |
177 | | // will be needed in order to (attempt to) allocate a contiguous block. |
178 | | static bool CC_ARM_AAPCS_Custom_Aggregate(unsigned &ValNo, MVT &ValVT, |
179 | | MVT &LocVT, |
180 | | CCValAssign::LocInfo &LocInfo, |
181 | | ISD::ArgFlagsTy &ArgFlags, |
182 | 5.08k | CCState &State) { |
183 | 5.08k | SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs(); |
184 | 5.08k | |
185 | 5.08k | // AAPCS HFAs must have 1-4 elements, all of the same type |
186 | 5.08k | if (PendingMembers.size() > 0) |
187 | 5.08k | assert(PendingMembers[0].getLocVT() == LocVT); |
188 | 5.08k | |
189 | 5.08k | // Add the argument to the list to be allocated once we know the size of the |
190 | 5.08k | // aggregate. Store the type's required alignmnent as extra info for later: in |
191 | 5.08k | // the [N x i64] case all trace has been removed by the time we actually get |
192 | 5.08k | // to do allocation. |
193 | 5.08k | PendingMembers.push_back(CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo, |
194 | 5.08k | ArgFlags.getOrigAlign())); |
195 | 5.08k | |
196 | 5.08k | if (!ArgFlags.isInConsecutiveRegsLast()) |
197 | 478 | return true; |
198 | 4.61k | |
199 | 4.61k | // Try to allocate a contiguous block of registers, each of the correct |
200 | 4.61k | // size to hold one member. |
201 | 4.61k | auto &DL = State.getMachineFunction().getDataLayout(); |
202 | 4.61k | unsigned StackAlign = DL.getStackAlignment(); |
203 | 4.61k | unsigned Align = std::min(PendingMembers[0].getExtraInfo(), StackAlign); |
204 | 4.61k | |
205 | 4.61k | ArrayRef<MCPhysReg> RegList; |
206 | 4.61k | switch (LocVT.SimpleTy) { |
207 | 4.61k | case MVT::i32: { |
208 | 183 | RegList = RRegList; |
209 | 183 | unsigned RegIdx = State.getFirstUnallocated(RegList); |
210 | 183 | |
211 | 183 | // First consume all registers that would give an unaligned object. Whether |
212 | 183 | // we go on stack or in regs, no-one will be using them in future. |
213 | 183 | unsigned RegAlign = alignTo(Align, 4) / 4; |
214 | 188 | while (RegIdx % RegAlign != 0 && RegIdx < RegList.size()5 ) |
215 | 5 | State.AllocateReg(RegList[RegIdx++]); |
216 | 183 | |
217 | 183 | break; |
218 | 4.61k | } |
219 | 4.61k | case MVT::f16: |
220 | 1.74k | case MVT::f32: |
221 | 1.74k | RegList = SRegList; |
222 | 1.74k | break; |
223 | 2.37k | case MVT::v4f16: |
224 | 2.37k | case MVT::f64: |
225 | 2.37k | RegList = DRegList; |
226 | 2.37k | break; |
227 | 2.37k | case MVT::v8f16: |
228 | 301 | case MVT::v2f64: |
229 | 301 | RegList = QRegList; |
230 | 301 | break; |
231 | 301 | default: |
232 | 0 | llvm_unreachable("Unexpected member type for block aggregate"); |
233 | 301 | break0 ; |
234 | 4.61k | } |
235 | 4.61k | |
236 | 4.61k | unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size()); |
237 | 4.61k | if (RegResult) { |
238 | 4.44k | for (SmallVectorImpl<CCValAssign>::iterator It = PendingMembers.begin(); |
239 | 9.15k | It != PendingMembers.end(); ++It4.71k ) { |
240 | 4.71k | It->convertToReg(RegResult); |
241 | 4.71k | State.addLoc(*It); |
242 | 4.71k | ++RegResult; |
243 | 4.71k | } |
244 | 4.44k | PendingMembers.clear(); |
245 | 4.44k | return true; |
246 | 4.44k | } |
247 | 163 | |
248 | 163 | // Register allocation failed, we'll be needing the stack |
249 | 163 | unsigned Size = LocVT.getSizeInBits() / 8; |
250 | 163 | if (LocVT == MVT::i32 && State.getNextStackOffset() == 092 ) { |
251 | 79 | // If nothing else has used the stack until this point, a non-HFA aggregate |
252 | 79 | // can be split between regs and stack. |
253 | 79 | unsigned RegIdx = State.getFirstUnallocated(RegList); |
254 | 242 | for (auto &It : PendingMembers) { |
255 | 242 | if (RegIdx >= RegList.size()) |
256 | 125 | It.convertToMem(State.AllocateStack(Size, Size)); |
257 | 117 | else |
258 | 117 | It.convertToReg(State.AllocateReg(RegList[RegIdx++])); |
259 | 242 | |
260 | 242 | State.addLoc(It); |
261 | 242 | } |
262 | 79 | PendingMembers.clear(); |
263 | 79 | return true; |
264 | 84 | } else if (LocVT != MVT::i32) |
265 | 71 | RegList = SRegList; |
266 | 163 | |
267 | 163 | // Mark all regs as unavailable (AAPCS rule C.2.vfp for VFP, C.6 for core) |
268 | 163 | for (auto Reg : RegList)84 |
269 | 1.18k | State.AllocateReg(Reg); |
270 | 84 | |
271 | 84 | // After the first item has been allocated, the rest are packed as tightly as |
272 | 84 | // possible. (E.g. an incoming i64 would have starting Align of 8, but we'll |
273 | 84 | // be allocating a bunch of i32 slots). |
274 | 84 | unsigned RestAlign = std::min(Align, Size); |
275 | 84 | |
276 | 134 | for (auto &It : PendingMembers) { |
277 | 134 | It.convertToMem(State.AllocateStack(Size, Align)); |
278 | 134 | State.addLoc(It); |
279 | 134 | Align = RestAlign; |
280 | 134 | } |
281 | 84 | |
282 | 84 | // All pending members have now been allocated |
283 | 84 | PendingMembers.clear(); |
284 | 84 | |
285 | 84 | // This will be allocated by the last member of the aggregate |
286 | 84 | return true; |
287 | 163 | } Unexecuted instantiation: ARMFastISel.cpp:llvm::CC_ARM_AAPCS_Custom_Aggregate(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) ARMISelLowering.cpp:llvm::CC_ARM_AAPCS_Custom_Aggregate(unsigned int&, llvm::MVT&, llvm::MVT&, llvm::CCValAssign::LocInfo&, llvm::ISD::ArgFlagsTy&, llvm::CCState&) Line | Count | Source | 182 | 5.08k | CCState &State) { | 183 | 5.08k | SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs(); | 184 | 5.08k | | 185 | 5.08k | // AAPCS HFAs must have 1-4 elements, all of the same type | 186 | 5.08k | if (PendingMembers.size() > 0) | 187 | 5.08k | assert(PendingMembers[0].getLocVT() == LocVT); | 188 | 5.08k | | 189 | 5.08k | // Add the argument to the list to be allocated once we know the size of the | 190 | 5.08k | // aggregate. Store the type's required alignmnent as extra info for later: in | 191 | 5.08k | // the [N x i64] case all trace has been removed by the time we actually get | 192 | 5.08k | // to do allocation. | 193 | 5.08k | PendingMembers.push_back(CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo, | 194 | 5.08k | ArgFlags.getOrigAlign())); | 195 | 5.08k | | 196 | 5.08k | if (!ArgFlags.isInConsecutiveRegsLast()) | 197 | 478 | return true; | 198 | 4.61k | | 199 | 4.61k | // Try to allocate a contiguous block of registers, each of the correct | 200 | 4.61k | // size to hold one member. | 201 | 4.61k | auto &DL = State.getMachineFunction().getDataLayout(); | 202 | 4.61k | unsigned StackAlign = DL.getStackAlignment(); | 203 | 4.61k | unsigned Align = std::min(PendingMembers[0].getExtraInfo(), StackAlign); | 204 | 4.61k | | 205 | 4.61k | ArrayRef<MCPhysReg> RegList; | 206 | 4.61k | switch (LocVT.SimpleTy) { | 207 | 4.61k | case MVT::i32: { | 208 | 183 | RegList = RRegList; | 209 | 183 | unsigned RegIdx = State.getFirstUnallocated(RegList); | 210 | 183 | | 211 | 183 | // First consume all registers that would give an unaligned object. Whether | 212 | 183 | // we go on stack or in regs, no-one will be using them in future. | 213 | 183 | unsigned RegAlign = alignTo(Align, 4) / 4; | 214 | 188 | while (RegIdx % RegAlign != 0 && RegIdx < RegList.size()5 ) | 215 | 5 | State.AllocateReg(RegList[RegIdx++]); | 216 | 183 | | 217 | 183 | break; | 218 | 4.61k | } | 219 | 4.61k | case MVT::f16: | 220 | 1.74k | case MVT::f32: | 221 | 1.74k | RegList = SRegList; | 222 | 1.74k | break; | 223 | 2.37k | case MVT::v4f16: | 224 | 2.37k | case MVT::f64: | 225 | 2.37k | RegList = DRegList; | 226 | 2.37k | break; | 227 | 2.37k | case MVT::v8f16: | 228 | 301 | case MVT::v2f64: | 229 | 301 | RegList = QRegList; | 230 | 301 | break; | 231 | 301 | default: | 232 | 0 | llvm_unreachable("Unexpected member type for block aggregate"); | 233 | 301 | break0 ; | 234 | 4.61k | } | 235 | 4.61k | | 236 | 4.61k | unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size()); | 237 | 4.61k | if (RegResult) { | 238 | 4.44k | for (SmallVectorImpl<CCValAssign>::iterator It = PendingMembers.begin(); | 239 | 9.15k | It != PendingMembers.end(); ++It4.71k ) { | 240 | 4.71k | It->convertToReg(RegResult); | 241 | 4.71k | State.addLoc(*It); | 242 | 4.71k | ++RegResult; | 243 | 4.71k | } | 244 | 4.44k | PendingMembers.clear(); | 245 | 4.44k | return true; | 246 | 4.44k | } | 247 | 163 | | 248 | 163 | // Register allocation failed, we'll be needing the stack | 249 | 163 | unsigned Size = LocVT.getSizeInBits() / 8; | 250 | 163 | if (LocVT == MVT::i32 && State.getNextStackOffset() == 092 ) { | 251 | 79 | // If nothing else has used the stack until this point, a non-HFA aggregate | 252 | 79 | // can be split between regs and stack. | 253 | 79 | unsigned RegIdx = State.getFirstUnallocated(RegList); | 254 | 242 | for (auto &It : PendingMembers) { | 255 | 242 | if (RegIdx >= RegList.size()) | 256 | 125 | It.convertToMem(State.AllocateStack(Size, Size)); | 257 | 117 | else | 258 | 117 | It.convertToReg(State.AllocateReg(RegList[RegIdx++])); | 259 | 242 | | 260 | 242 | State.addLoc(It); | 261 | 242 | } | 262 | 79 | PendingMembers.clear(); | 263 | 79 | return true; | 264 | 84 | } else if (LocVT != MVT::i32) | 265 | 71 | RegList = SRegList; | 266 | 163 | | 267 | 163 | // Mark all regs as unavailable (AAPCS rule C.2.vfp for VFP, C.6 for core) | 268 | 163 | for (auto Reg : RegList)84 | 269 | 1.18k | State.AllocateReg(Reg); | 270 | 84 | | 271 | 84 | // After the first item has been allocated, the rest are packed as tightly as | 272 | 84 | // possible. (E.g. an incoming i64 would have starting Align of 8, but we'll | 273 | 84 | // be allocating a bunch of i32 slots). | 274 | 84 | unsigned RestAlign = std::min(Align, Size); | 275 | 84 | | 276 | 134 | for (auto &It : PendingMembers) { | 277 | 134 | It.convertToMem(State.AllocateStack(Size, Align)); | 278 | 134 | State.addLoc(It); | 279 | 134 | Align = RestAlign; | 280 | 134 | } | 281 | 84 | | 282 | 84 | // All pending members have now been allocated | 283 | 84 | PendingMembers.clear(); | 284 | 84 | | 285 | 84 | // This will be allocated by the last member of the aggregate | 286 | 84 | return true; | 287 | 163 | } |
|
288 | | |
289 | | } // End llvm namespace |
290 | | |
291 | | #endif |