OLD | NEW |
---|---|
1 //===- subzero/src/IceIntrinsics.cpp - Functions related to intrinsics ----===// | 1 //===- subzero/src/IceIntrinsics.cpp - Functions related to intrinsics ----===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements the Intrinsics utilities for matching and | 10 // This file implements the Intrinsics utilities for matching and |
11 // then dispatching by name. | 11 // then dispatching by name. |
12 // | 12 // |
13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
14 | 14 |
15 #include "IceCfg.h" | 15 #include "IceCfg.h" |
16 #include "IceCfgNode.h" | 16 #include "IceCfgNode.h" |
17 #include "IceIntrinsics.h" | 17 #include "IceIntrinsics.h" |
18 #include "IceLiveness.h" | 18 #include "IceLiveness.h" |
19 #include "IceOperand.h" | 19 #include "IceOperand.h" |
20 | 20 |
21 #include <utility> | 21 #include <utility> |
22 | 22 |
23 namespace Ice { | 23 namespace Ice { |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 void __attribute__((unused)) xIntrinsicInfoSizeCheck() { | |
28 STATIC_ASSERT(sizeof(Intrinsics::IntrinsicInfo) == 4); | |
29 } | |
30 | |
31 #define INTRIN(ID, SE, RT) { Intrinsics::ID, Intrinsics::SE, Intrinsics::RT } | |
32 | |
33 // Build list of intrinsics with their attributes and expected prototypes. | |
34 // List is sorted alphabetically. | |
27 const struct IceIntrinsicsEntry_ { | 35 const struct IceIntrinsicsEntry_ { |
28 Intrinsics::FullIntrinsicInfo Info; | 36 Intrinsics::FullIntrinsicInfo Info; |
29 const char *IntrinsicName; | 37 const char *IntrinsicName; |
30 } IceIntrinsicsTable[] = { | 38 } IceIntrinsicsTable[] = { |
39 | |
31 #define AtomicCmpxchgInit(Overload, NameSuffix) \ | 40 #define AtomicCmpxchgInit(Overload, NameSuffix) \ |
32 { \ | 41 { \ |
33 { \ | 42 { \ |
34 { Intrinsics::AtomicCmpxchg, true }, \ | 43 INTRIN(AtomicCmpxchg, SideEffects_T, ReturnsTwice_F), \ |
35 { Overload, IceType_i32, Overload, Overload, IceType_i32, IceType_i32 }, \ | 44 { Overload, IceType_i32, Overload, Overload, IceType_i32, IceType_i32 }, \ |
36 6 \ | 45 6 }, \ |
37 } \ | 46 "nacl.atomic.cmpxchg." NameSuffix \ |
38 , "nacl.atomic.cmpxchg." NameSuffix \ | |
39 } | 47 } |
40 AtomicCmpxchgInit(IceType_i8, "i8"), | 48 AtomicCmpxchgInit(IceType_i8, "i8"), |
41 AtomicCmpxchgInit(IceType_i16, "i16"), | 49 AtomicCmpxchgInit(IceType_i16, "i16"), |
42 AtomicCmpxchgInit(IceType_i32, "i32"), | 50 AtomicCmpxchgInit(IceType_i32, "i32"), |
43 AtomicCmpxchgInit(IceType_i64, "i64"), | 51 AtomicCmpxchgInit(IceType_i64, "i64"), |
44 #undef AtomicCmpxchgInit | 52 #undef AtomicCmpxchgInit |
45 { { { Intrinsics::AtomicFence, true }, { IceType_void, IceType_i32 }, 2 }, | 53 |
54 { { INTRIN(AtomicFence, SideEffects_T, ReturnsTwice_F), | |
55 { IceType_void, IceType_i32 }, 2 }, | |
46 "nacl.atomic.fence" }, | 56 "nacl.atomic.fence" }, |
47 { { { Intrinsics::AtomicFenceAll, true }, { IceType_void }, 1 }, | 57 { { INTRIN(AtomicFenceAll, SideEffects_T, ReturnsTwice_F), |
58 { IceType_void }, 1 }, | |
48 "nacl.atomic.fence.all" }, | 59 "nacl.atomic.fence.all" }, |
49 { { { Intrinsics::AtomicIsLockFree, false }, | 60 { { INTRIN(AtomicIsLockFree, SideEffects_F, ReturnsTwice_F), |
50 { IceType_i1, IceType_i32, IceType_i32 }, 3 }, | 61 { IceType_i1, IceType_i32, IceType_i32 }, 3 }, |
51 "nacl.atomic.is.lock.free" }, | 62 "nacl.atomic.is.lock.free" }, |
52 | 63 |
53 #define AtomicLoadInit(Overload, NameSuffix) \ | 64 #define AtomicLoadInit(Overload, NameSuffix) \ |
54 { \ | 65 { \ |
55 { \ | 66 { \ |
56 { Intrinsics::AtomicLoad, true } \ | 67 INTRIN(AtomicLoad, SideEffects_T, ReturnsTwice_F), \ |
57 , { Overload, IceType_i32, IceType_i32 }, 3 \ | 68 { Overload, IceType_i32, IceType_i32 }, 3 }, \ |
58 } \ | 69 "nacl.atomic.load." NameSuffix \ |
Jim Stichnoth
2014/09/11 22:26:26
line up the backslashes
| |
59 , "nacl.atomic.load." NameSuffix \ | |
60 } | 70 } |
61 AtomicLoadInit(IceType_i8, "i8"), | 71 AtomicLoadInit(IceType_i8, "i8"), |
62 AtomicLoadInit(IceType_i16, "i16"), | 72 AtomicLoadInit(IceType_i16, "i16"), |
63 AtomicLoadInit(IceType_i32, "i32"), | 73 AtomicLoadInit(IceType_i32, "i32"), |
64 AtomicLoadInit(IceType_i64, "i64"), | 74 AtomicLoadInit(IceType_i64, "i64"), |
65 #undef AtomicLoadInit | 75 #undef AtomicLoadInit |
66 | 76 |
67 #define AtomicRMWInit(Overload, NameSuffix) \ | 77 #define AtomicRMWInit(Overload, NameSuffix) \ |
68 { \ | 78 { \ |
69 { \ | 79 { \ |
70 { Intrinsics::AtomicRMW, true } \ | 80 INTRIN(AtomicRMW, SideEffects_T, ReturnsTwice_F) \ |
71 , { Overload, IceType_i32, IceType_i32, Overload, IceType_i32 }, 5 \ | 81 , { Overload, IceType_i32, IceType_i32, Overload, IceType_i32 }, 5 \ |
72 } \ | 82 } \ |
73 , "nacl.atomic.rmw." NameSuffix \ | 83 , "nacl.atomic.rmw." NameSuffix \ |
74 } | 84 } |
75 AtomicRMWInit(IceType_i8, "i8"), | 85 AtomicRMWInit(IceType_i8, "i8"), |
76 AtomicRMWInit(IceType_i16, "i16"), | 86 AtomicRMWInit(IceType_i16, "i16"), |
77 AtomicRMWInit(IceType_i32, "i32"), | 87 AtomicRMWInit(IceType_i32, "i32"), |
78 AtomicRMWInit(IceType_i64, "i64"), | 88 AtomicRMWInit(IceType_i64, "i64"), |
79 #undef AtomicRMWInit | 89 #undef AtomicRMWInit |
80 | 90 |
81 #define AtomicStoreInit(Overload, NameSuffix) \ | 91 #define AtomicStoreInit(Overload, NameSuffix) \ |
82 { \ | 92 { \ |
83 { \ | 93 { \ |
84 { Intrinsics::AtomicStore, true } \ | 94 INTRIN(AtomicStore, SideEffects_T, ReturnsTwice_F) \ |
85 , { IceType_void, Overload, IceType_i32, IceType_i32 }, 4 \ | 95 , { IceType_void, Overload, IceType_i32, IceType_i32 }, 4 \ |
86 } \ | 96 } \ |
87 , "nacl.atomic.store." NameSuffix \ | 97 , "nacl.atomic.store." NameSuffix \ |
88 } | 98 } |
89 AtomicStoreInit(IceType_i8, "i8"), | 99 AtomicStoreInit(IceType_i8, "i8"), |
90 AtomicStoreInit(IceType_i16, "i16"), | 100 AtomicStoreInit(IceType_i16, "i16"), |
91 AtomicStoreInit(IceType_i32, "i32"), | 101 AtomicStoreInit(IceType_i32, "i32"), |
92 AtomicStoreInit(IceType_i64, "i64"), | 102 AtomicStoreInit(IceType_i64, "i64"), |
93 #undef AtomicStoreInit | 103 #undef AtomicStoreInit |
94 | 104 |
95 #define BswapInit(Overload, NameSuffix) \ | 105 #define BswapInit(Overload, NameSuffix) \ |
96 { \ | 106 { \ |
97 { \ | 107 { \ |
98 { Intrinsics::Bswap, false } \ | 108 INTRIN(Bswap, SideEffects_F, ReturnsTwice_F) \ |
99 , { Overload, Overload }, 2 \ | 109 , { Overload, Overload }, 2 \ |
100 } \ | 110 } \ |
101 , "bswap." NameSuffix \ | 111 , "bswap." NameSuffix \ |
102 } | 112 } |
103 BswapInit(IceType_i16, "i16"), | 113 BswapInit(IceType_i16, "i16"), |
104 BswapInit(IceType_i32, "i32"), | 114 BswapInit(IceType_i32, "i32"), |
105 BswapInit(IceType_i64, "i64"), | 115 BswapInit(IceType_i64, "i64"), |
106 #undef BswapInit | 116 #undef BswapInit |
107 | 117 |
108 #define CtlzInit(Overload, NameSuffix) \ | 118 #define CtlzInit(Overload, NameSuffix) \ |
109 { \ | 119 { \ |
110 { \ | 120 { \ |
111 { Intrinsics::Ctlz, false } \ | 121 INTRIN(Ctlz, SideEffects_F, ReturnsTwice_F) \ |
112 , { Overload, Overload, IceType_i1 }, 3 \ | 122 , { Overload, Overload, IceType_i1 }, 3 \ |
113 } \ | 123 } \ |
114 , "ctlz." NameSuffix \ | 124 , "ctlz." NameSuffix \ |
115 } | 125 } |
116 CtlzInit(IceType_i32, "i32"), | 126 CtlzInit(IceType_i32, "i32"), |
117 CtlzInit(IceType_i64, "i64"), | 127 CtlzInit(IceType_i64, "i64"), |
118 #undef CtlzInit | 128 #undef CtlzInit |
119 | 129 |
120 #define CtpopInit(Overload, NameSuffix) \ | 130 #define CtpopInit(Overload, NameSuffix) \ |
121 { \ | 131 { \ |
122 { \ | 132 { \ |
123 { Intrinsics::Ctpop, false } \ | 133 INTRIN(Ctpop, SideEffects_F, ReturnsTwice_F) \ |
124 , { Overload, Overload }, 2 \ | 134 , { Overload, Overload }, 2 \ |
125 } \ | 135 } \ |
126 , "ctpop." NameSuffix \ | 136 , "ctpop." NameSuffix \ |
127 } | 137 } |
128 CtpopInit(IceType_i32, "i32"), | 138 CtpopInit(IceType_i32, "i32"), |
129 CtpopInit(IceType_i64, "i64"), | 139 CtpopInit(IceType_i64, "i64"), |
130 #undef CtpopInit | 140 #undef CtpopInit |
131 | 141 |
132 #define CttzInit(Overload, NameSuffix) \ | 142 #define CttzInit(Overload, NameSuffix) \ |
133 { \ | 143 { \ |
134 { \ | 144 { \ |
135 { Intrinsics::Cttz, false } \ | 145 INTRIN(Cttz, SideEffects_F, ReturnsTwice_F) \ |
136 , { Overload, Overload, IceType_i1 }, 3 \ | 146 , { Overload, Overload, IceType_i1 }, 3 \ |
137 } \ | 147 } \ |
138 , "cttz." NameSuffix \ | 148 , "cttz." NameSuffix \ |
139 } | 149 } |
140 CttzInit(IceType_i32, "i32"), | 150 CttzInit(IceType_i32, "i32"), |
141 CttzInit(IceType_i64, "i64"), | 151 CttzInit(IceType_i64, "i64"), |
142 #undef CttzInit | 152 #undef CttzInit |
143 { { { Intrinsics::Longjmp, true }, | 153 |
154 { { INTRIN(Longjmp, SideEffects_T, ReturnsTwice_F), | |
144 { IceType_void, IceType_i32, IceType_i32 }, 3 }, | 155 { IceType_void, IceType_i32, IceType_i32 }, 3 }, |
145 "nacl.longjmp" }, | 156 "nacl.longjmp" }, |
146 { { { Intrinsics::Memcpy, true }, { IceType_void, IceType_i32, IceType_i32, | 157 { { INTRIN(Memcpy, SideEffects_T, ReturnsTwice_F), |
147 IceType_i32, IceType_i32, IceType_i1 }, | 158 { IceType_void, IceType_i32, IceType_i32, IceType_i32, IceType_i32, |
159 IceType_i1}, | |
148 6 }, | 160 6 }, |
149 "memcpy.p0i8.p0i8.i32" }, | 161 "memcpy.p0i8.p0i8.i32" }, |
150 { { { Intrinsics::Memmove, true }, | 162 { { INTRIN(Memmove, SideEffects_T, ReturnsTwice_F), |
151 { IceType_void, IceType_i32, IceType_i32, | 163 { IceType_void, IceType_i32, IceType_i32, IceType_i32, IceType_i32, |
152 IceType_i32, IceType_i32, IceType_i1 }, | 164 IceType_i1 }, |
153 6 }, | 165 6 }, |
154 "memmove.p0i8.p0i8.i32" }, | 166 "memmove.p0i8.p0i8.i32" }, |
155 { { { Intrinsics::Memset, true }, { IceType_void, IceType_i32, IceType_i8, | 167 { { INTRIN(Memset, SideEffects_T, ReturnsTwice_F), |
156 IceType_i32, IceType_i32, IceType_i1 }, | 168 { IceType_void, IceType_i32, IceType_i8, IceType_i32, IceType_i32, |
169 IceType_i1 }, | |
157 6 }, | 170 6 }, |
158 "memset.p0i8.i32" }, | 171 "memset.p0i8.i32" }, |
159 { { { Intrinsics::NaClReadTP, false }, { IceType_i32 }, 1 }, | 172 { { INTRIN(NaClReadTP, SideEffects_F, ReturnsTwice_F), |
173 { IceType_i32 }, 1 }, | |
160 "nacl.read.tp" }, | 174 "nacl.read.tp" }, |
161 { { { Intrinsics::Setjmp, true }, { IceType_i32, IceType_i32 }, 2 }, | 175 { { INTRIN(Setjmp, SideEffects_T, ReturnsTwice_T), |
176 { IceType_i32, IceType_i32 }, 2 }, | |
162 "nacl.setjmp" }, | 177 "nacl.setjmp" }, |
163 | 178 |
164 #define SqrtInit(Overload, NameSuffix) \ | 179 #define SqrtInit(Overload, NameSuffix) \ |
165 { \ | 180 { \ |
166 { \ | 181 { \ |
167 { Intrinsics::Sqrt, false } \ | 182 INTRIN(Sqrt, SideEffects_F, ReturnsTwice_F), \ |
168 , { Overload, Overload }, 2 \ | 183 { Overload, Overload }, 2 }, \ |
169 } \ | 184 "sqrt." NameSuffix \ |
170 , "sqrt." NameSuffix \ | |
171 } | 185 } |
172 SqrtInit(IceType_f32, "f32"), | 186 SqrtInit(IceType_f32, "f32"), |
173 SqrtInit(IceType_f64, "f64"), | 187 SqrtInit(IceType_f64, "f64"), |
174 #undef SqrtInit | 188 #undef SqrtInit |
175 { { { Intrinsics::Stacksave, true }, { IceType_i32 }, 1 }, "stacksave" }, | 189 |
176 { { { Intrinsics::Stackrestore, true }, { IceType_void, IceType_i32 }, 2 }, | 190 { { INTRIN(Stacksave, SideEffects_T, ReturnsTwice_F), |
191 { IceType_i32 }, 1 }, | |
192 "stacksave" }, | |
193 { { INTRIN(Stackrestore, SideEffects_T, ReturnsTwice_F), | |
194 { IceType_void, IceType_i32 }, 2 }, | |
177 "stackrestore" }, | 195 "stackrestore" }, |
178 { { { Intrinsics::Trap, true }, { IceType_void }, 1 }, "trap" } | 196 { { INTRIN(Trap, SideEffects_T, ReturnsTwice_F), |
179 }; | 197 { IceType_void }, 1 }, |
198 "trap" } | |
199 }; | |
180 const size_t IceIntrinsicsTableSize = llvm::array_lengthof(IceIntrinsicsTable); | 200 const size_t IceIntrinsicsTableSize = llvm::array_lengthof(IceIntrinsicsTable); |
181 | 201 |
202 #undef INTRIN | |
203 | |
182 } // end of anonymous namespace | 204 } // end of anonymous namespace |
183 | 205 |
184 Intrinsics::Intrinsics() { | 206 Intrinsics::Intrinsics() { |
185 for (size_t I = 0; I < IceIntrinsicsTableSize; ++I) { | 207 for (size_t I = 0; I < IceIntrinsicsTableSize; ++I) { |
186 const struct IceIntrinsicsEntry_ &Entry = IceIntrinsicsTable[I]; | 208 const struct IceIntrinsicsEntry_ &Entry = IceIntrinsicsTable[I]; |
187 assert(Entry.Info.NumTypes <= kMaxIntrinsicParameters); | 209 assert(Entry.Info.NumTypes <= kMaxIntrinsicParameters); |
188 map.insert(std::make_pair(IceString(Entry.IntrinsicName), Entry.Info)); | 210 map.insert(std::make_pair(IceString(Entry.IntrinsicName), Entry.Info)); |
189 } | 211 } |
190 } | 212 } |
191 | 213 |
192 Intrinsics::~Intrinsics() {} | 214 Intrinsics::~Intrinsics() {} |
193 | 215 |
194 const Intrinsics::FullIntrinsicInfo * | 216 const Intrinsics::FullIntrinsicInfo * |
195 Intrinsics::find(const IceString &Name) const { | 217 Intrinsics::find(const IceString &Name) const { |
196 IntrinsicMap::const_iterator it = map.find(Name); | 218 IntrinsicMap::const_iterator it = map.find(Name); |
197 if (it == map.end()) | 219 if (it == map.end()) |
198 return NULL; | 220 return NULL; |
199 return &it->second; | 221 return &it->second; |
200 } | 222 } |
201 | 223 |
202 bool Intrinsics::VerifyMemoryOrder(uint64_t Order) { | 224 bool Intrinsics::VerifyMemoryOrder(uint64_t Order) { |
203 // There is only one memory ordering for atomics allowed right now. | 225 // There is only one memory ordering for atomics allowed right now. |
204 return Order == Intrinsics::MemoryOrderSequentiallyConsistent; | 226 return Order == Intrinsics::MemoryOrderSequentiallyConsistent; |
205 } | 227 } |
206 | 228 |
207 } // end of namespace Ice | 229 } // end of namespace Ice |
OLD | NEW |