|
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