|
1 | 1 | // This file is a part of Julia. License is MIT: https://julialang.org/license
|
2 | 2 |
|
3 | 3 | #include "llvm-gc-interface-passes.h"
|
| 4 | +#include "llvm/IR/Intrinsics.h" |
| 5 | +#include "llvm/Support/Casting.h" |
4 | 6 |
|
5 | 7 | #define DEBUG_TYPE "late_lower_gcroot"
|
6 | 8 |
|
@@ -171,12 +173,12 @@ static std::pair<Value*,int> FindBaseValue(const State &S, Value *V, bool UseCac
|
171 | 173 | (void)LI;
|
172 | 174 | break;
|
173 | 175 | }
|
174 |
| - else if (auto II = dyn_cast<IntrinsicInst>(CurrentV)) { |
175 |
| - // Some intrinsics behave like LoadInst followed by a SelectInst |
176 |
| - // This should never happen in a derived addrspace (since those cannot be stored to memory) |
177 |
| - // so we don't need to lift these operations, but we do need to check if it's loaded and continue walking the base pointer |
| 176 | + else if (auto *II = dyn_cast<IntrinsicInst>(CurrentV)) { |
178 | 177 | if (II->getIntrinsicID() == Intrinsic::masked_load ||
|
179 | 178 | II->getIntrinsicID() == Intrinsic::masked_gather) {
|
| 179 | + // Some intrinsics behave like LoadInst followed by a SelectInst |
| 180 | + // This should never happen in a derived addrspace (since those cannot be stored to memory) |
| 181 | + // so we don't need to lift these operations, but we do need to check if it's loaded and continue walking the base pointer |
180 | 182 | if (auto VTy = dyn_cast<VectorType>(II->getType())) {
|
181 | 183 | if (hasLoadedTy(VTy->getElementType())) {
|
182 | 184 | Value *Mask = II->getOperand(2);
|
@@ -205,16 +207,36 @@ static std::pair<Value*,int> FindBaseValue(const State &S, Value *V, bool UseCac
|
205 | 207 | // In general a load terminates a walk
|
206 | 208 | break;
|
207 | 209 | }
|
| 210 | + else if (II->getIntrinsicID() == Intrinsic::vector_extract) { |
| 211 | + if (auto VTy = dyn_cast<VectorType>(II->getType())) { |
| 212 | + if (hasLoadedTy(VTy->getElementType())) { |
| 213 | + Value *Idx = II->getOperand(1); |
| 214 | + if (!isa<ConstantInt>(Idx)) { |
| 215 | + assert(isa<UndefValue>(Idx) && "unimplemented"); |
| 216 | + (void)Idx; |
| 217 | + } |
| 218 | + CurrentV = II->getOperand(0); |
| 219 | + fld_idx = -1; |
| 220 | + continue; |
| 221 | + } |
| 222 | + } |
| 223 | + break; |
| 224 | + } else { |
| 225 | + // Unknown Intrinsic |
| 226 | + break; |
| 227 | + } |
208 | 228 | }
|
209 | 229 | else if (auto CI = dyn_cast<CallInst>(CurrentV)) {
|
210 | 230 | auto callee = CI->getCalledFunction();
|
211 | 231 | if (callee && callee->getName() == "julia.gc_loaded") {
|
212 | 232 | CurrentV = CI->getArgOperand(0);
|
213 | 233 | continue;
|
214 | 234 | }
|
| 235 | + // Unknown Call |
215 | 236 | break;
|
216 | 237 | }
|
217 | 238 | else {
|
| 239 | + // Unknown Instruction |
218 | 240 | break;
|
219 | 241 | }
|
220 | 242 | }
|
@@ -518,6 +540,22 @@ SmallVector<int, 0> LateLowerGCFrame::NumberAllBase(State &S, Value *CurrentV) {
|
518 | 540 | Numbers = NumberAll(S, IEI->getOperand(0));
|
519 | 541 | int ElNumber = Number(S, IEI->getOperand(1));
|
520 | 542 | Numbers[idx] = ElNumber;
|
| 543 | + // C++17 |
| 544 | + // } else if (auto *II = dyn_cast<IntrinsicInst>(CurrentV); II && II->getIntrinsicID() == Intrinsic::vector_insert) { |
| 545 | + } else if (isa<IntrinsicInst>(CurrentV) && cast<IntrinsicInst>(CurrentV)->getIntrinsicID() == Intrinsic::vector_insert) { |
| 546 | + auto *II = dyn_cast<IntrinsicInst>(CurrentV); |
| 547 | + // Vector insert is a bit like a shuffle so use the same approach |
| 548 | + SmallVector<int, 0> Numbers1 = NumberAll(S, II->getOperand(0)); |
| 549 | + SmallVector<int, 0> Numbers2 = NumberAll(S, II->getOperand(1)); |
| 550 | + unsigned first_idx = cast<ConstantInt>(II->getOperand(2))->getZExtValue(); |
| 551 | + for (unsigned i = 0; i < Numbers1.size(); ++i) { |
| 552 | + if (i < first_idx) |
| 553 | + Numbers.push_back(Numbers1[i]); |
| 554 | + else if (i - first_idx < Numbers2.size()) |
| 555 | + Numbers.push_back(Numbers2[i - first_idx]); |
| 556 | + else |
| 557 | + Numbers.push_back(Numbers1[i]); |
| 558 | + } |
521 | 559 | } else if (auto *IVI = dyn_cast<InsertValueInst>(CurrentV)) {
|
522 | 560 | Numbers = NumberAll(S, IVI->getAggregateOperand());
|
523 | 561 | auto Tracked = TrackCompositeType(IVI->getType());
|
@@ -1150,6 +1188,10 @@ State LateLowerGCFrame::LocalScan(Function &F) {
|
1150 | 1188 | }
|
1151 | 1189 | }
|
1152 | 1190 | }
|
| 1191 | + if (II->getIntrinsicID() == Intrinsic::vector_extract || II->getIntrinsicID() == Intrinsic::vector_insert) { |
| 1192 | + // These are not real defs |
| 1193 | + continue; |
| 1194 | + } |
1153 | 1195 | }
|
1154 | 1196 | auto callee = CI->getCalledFunction();
|
1155 | 1197 | if (callee && callee == typeof_func) {
|
|
0 commit comments