已合并
fix: tail call opt, stackmap opt #583
jiadiliu创建于 7月24日
fix: tail call opt, stackmap opt #583
已合并
共 51 个文件变更+411-240
| @@ -162,11 +162,26 @@ public: | |||
| 162 | ItemIdxHelper<LineNumberItem> LNItems; | 162 | ItemIdxHelper<LineNumberItem> LNItems; |
| 163 | // <regIdxPlusOne, slotIdxPlusOne> | 163 | // <regIdxPlusOne, slotIdxPlusOne> |
| 164 | std::vector<std::pair<unsigned, unsigned>> DerivedInfo; | 164 | std::vector<std::pair<unsigned, unsigned>> DerivedInfo; |
| 165 | + std::map<std::vector<std::pair<unsigned, unsigned>>, unsigned> | ||
| 166 | + DerivedInfo2StartIdx; | ||
| 165 | 167 | ||
| 166 | MaxBitsInfo MaxBits; | 168 | MaxBitsInfo MaxBits; |
| 167 | // unordered_map<regNo, bitIdx>, regNo can be used to find callee saved reg | 169 | // unordered_map<regNo, bitIdx>, regNo can be used to find callee saved reg |
| 168 | // while bitIdx is used in prologue. | 170 | // while bitIdx is used in prologue. |
| 169 | const std::unordered_map<uint32_t, uint32_t> &CSRegMap; | 171 | const std::unordered_map<uint32_t, uint32_t> &CSRegMap; |
| 172 | + | ||
| 173 | + unsigned getOrInsertDerivedInfoStartIdx( | ||
| 174 | + const std::vector<std::pair<unsigned, unsigned>> &Items) { | ||
| 175 | + auto Itr = DerivedInfo2StartIdx.find(Items); | ||
| 176 | + if (Itr != DerivedInfo2StartIdx.end()) { | ||
| 177 | + return Itr->second; | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + unsigned StartIdx = DerivedInfo.size(); | ||
| 181 | + DerivedInfo.insert(DerivedInfo.end(), Items.begin(), Items.end()); | ||
| 182 | + DerivedInfo2StartIdx.emplace(Items, StartIdx); | ||
| 183 | + return StartIdx; | ||
| 184 | + } | ||
| 170 | }; | 185 | }; |
| 171 | 186 | ||
| 172 | class DataEncoder { | 187 | class DataEncoder { |
| @@ -25,6 +25,12 @@ enum { | |||
| 25 | }; | 25 | }; |
| 26 | } // end namespace TargetOpcode | 26 | } // end namespace TargetOpcode |
| 27 | 27 | ||
| 28 | +/// Check whether the given opcode is a statepoint pseudo instruction. | ||
| 29 | +inline bool isStatepointOpcode(unsigned Opcode) { | ||
| 30 | + return Opcode == TargetOpcode::STATEPOINT || | ||
| 31 | + Opcode == TargetOpcode::STATEPOINT_TAIL_CALL; | ||
| 32 | +} | ||
| 33 | + | ||
| 28 | /// Check whether the given Opcode is a generic opcode that is not supposed | 34 | /// Check whether the given Opcode is a generic opcode that is not supposed |
| 29 | /// to appear after ISel. | 35 | /// to appear after ISel. |
| 30 | inline bool isPreISelGenericOpcode(unsigned Opcode) { | 36 | inline bool isPreISelGenericOpcode(unsigned Opcode) { |
| @@ -157,6 +157,10 @@ HANDLE_TARGET_OPCODE(PREALLOCATED_ARG) | |||
| 157 | /// collectors and deoptimizations in either the callee or caller. | 157 | /// collectors and deoptimizations in either the callee or caller. |
| 158 | HANDLE_TARGET_OPCODE(STATEPOINT) | 158 | HANDLE_TARGET_OPCODE(STATEPOINT) |
| 159 | 159 | ||
| 160 | +/// Tail call form of STATEPOINT. It carries the same operands as STATEPOINT, | ||
| 161 | +/// but is lowered as a tail call by the target AsmPrinter. | ||
| 162 | +HANDLE_TARGET_OPCODE(STATEPOINT_TAIL_CALL) | ||
| 163 | + | ||
| 160 | /// Instruction that records the offset of a local stack allocation passed to | 164 | /// Instruction that records the offset of a local stack allocation passed to |
| 161 | /// llvm.localescape. It has two arguments: the symbol for the label and the | 165 | /// llvm.localescape. It has two arguments: the symbol for the label and the |
| 162 | /// frame index of the local stack allocation. | 166 | /// frame index of the local stack allocation. |
| @@ -1286,6 +1286,18 @@ def STATEPOINT : StandardPseudoInstruction { | |||
| 1286 | let hasSideEffects = true; | 1286 | let hasSideEffects = true; |
| 1287 | let isCall = true; | 1287 | let isCall = true; |
| 1288 | } | 1288 | } |
| 1289 | +def STATEPOINT_TAIL_CALL : StandardPseudoInstruction { | ||
| 1290 | + let OutOperandList = (outs variable_ops); | ||
| 1291 | + let InOperandList = (ins variable_ops); | ||
| 1292 | + let usesCustomInserter = true; | ||
| 1293 | + let mayLoad = true; | ||
| 1294 | + let mayStore = true; | ||
| 1295 | + let hasSideEffects = true; | ||
| 1296 | + let isCall = true; | ||
| 1297 | + let isTerminator = true; | ||
| 1298 | + let isReturn = true; | ||
| 1299 | + let isBarrier = true; | ||
| 1300 | +} | ||
| 1289 | def LOAD_STACK_GUARD : StandardPseudoInstruction { | 1301 | def LOAD_STACK_GUARD : StandardPseudoInstruction { |
| 1290 | let OutOperandList = (outs ptr_rc:$dst); | 1302 | let OutOperandList = (outs ptr_rc:$dst); |
| 1291 | let InOperandList = (ins); | 1303 | let InOperandList = (ins); |
| @@ -3518,7 +3518,7 @@ static bool isNonStackOverflowFunc(MachineFunction &MF, unsigned FrameSize) { | |||
| 3518 | 3518 | ||
| 3519 | for (MachineBasicBlock &BB : MF) { | 3519 | for (MachineBasicBlock &BB : MF) { |
| 3520 | for (MachineInstr &MI : BB) { | 3520 | for (MachineInstr &MI : BB) { |
| 3521 | - if (MI.getOpcode() != TargetOpcode::STATEPOINT) | 3521 | + if (!isStatepointOpcode(MI.getOpcode())) |
| 3522 | continue; | 3522 | continue; |
| 3523 | 3523 | ||
| 3524 | StatepointOpers SO(&MI); | 3524 | StatepointOpers SO(&MI); |
| @@ -4193,7 +4193,7 @@ bool AsmPrinter::tryEmitCangjieSpecificCall(const MachineInstr *MI) { | |||
| 4193 | 4193 | ||
| 4194 | unsigned Opcode = MI->getOpcode(); | 4194 | unsigned Opcode = MI->getOpcode(); |
| 4195 | // statepoint call will be processed by LowerSTATEPOINT | 4195 | // statepoint call will be processed by LowerSTATEPOINT |
| 4196 | - if (Opcode == TargetOpcode::STATEPOINT) { | 4196 | + if (isStatepointOpcode(Opcode)) { |
| 4197 | return false; | 4197 | return false; |
| 4198 | } | 4198 | } |
| 4199 | 4199 | ||
| @@ -30,6 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | + | ||
| 33 | 34 | ||
| 34 | 35 | ||
| 35 | 36 | ||
| @@ -1978,7 +1979,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { | |||
| 1978 | }; | 1979 | }; |
| 1979 | 1980 | ||
| 1980 | auto IsCangjieSafepoint = [this](const MachineInstr *MI) { | 1981 | auto IsCangjieSafepoint = [this](const MachineInstr *MI) { |
| 1981 | - return MI->getOpcode() != TargetOpcode::STATEPOINT | 1982 | + return !isStatepointOpcode(MI->getOpcode()) |
| 1982 | ? false | 1983 | ? false |
| 1983 | : StatepointOpers(MI).getID() == | 1984 | : StatepointOpers(MI).getID() == |
| 1984 | Cangjie::CJStatepointID::SafepointStub && | 1985 | Cangjie::CJStatepointID::SafepointStub && |
| @@ -2092,7 +2093,7 @@ static DebugLoc findPrologueEndLoc(const MachineFunction *MF) { | |||
| 2092 | // First known non-DBG_VALUE and non-frame setup location marks | 2093 | // First known non-DBG_VALUE and non-frame setup location marks |
| 2093 | // the beginning of the function body. | 2094 | // the beginning of the function body. |
| 2094 | auto IsCangjieSafepoint = [](const MachineInstr *MI) { | 2095 | auto IsCangjieSafepoint = [](const MachineInstr *MI) { |
| 2095 | - return MI->getOpcode() != TargetOpcode::STATEPOINT | 2096 | + return !isStatepointOpcode(MI->getOpcode()) |
| 2096 | ? false | 2097 | ? false |
| 2097 | : StatepointOpers(MI).getID() == | 2098 | : StatepointOpers(MI).getID() == |
| 2098 | Cangjie::CJStatepointID::SafepointStub; | 2099 | Cangjie::CJStatepointID::SafepointStub; |
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | + | ||
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | 31 | ||
| @@ -767,7 +768,7 @@ void CJStackPointerInserter::getAnalysisUsage(AnalysisUsage &AU) const { | |||
| 767 | } | 768 | } |
| 768 | 769 | ||
| 769 | bool CJStackPointerInserter::needRewriteCall(MachineInstr &MI) { | 770 | bool CJStackPointerInserter::needRewriteCall(MachineInstr &MI) { |
| 770 | - if (MI.getOpcode() != TargetOpcode::STATEPOINT) | 771 | + if (!isStatepointOpcode(MI.getOpcode())) |
| 771 | return false; | 772 | return false; |
| 772 | 773 | ||
| 773 | StatepointOpers SO(&MI); | 774 | StatepointOpers SO(&MI); |
| @@ -900,7 +901,17 @@ bool CJStackPointerInserter::rewriteStatepoint(MachineFunction &MF, | |||
| 900 | MIB.add(MO); | 901 | MIB.add(MO); |
| 901 | } | 902 | } |
| 902 | } | 903 | } |
| 903 | - MI.getParent()->insert(MI.getNextNode(), MIB); | 904 | + // STATEPOINT_TAIL_CALL is a terminator (isTerminator/isReturn) and is the |
| 905 | + // last instruction in its block, so MI.getNextNode() is null. Insert the | ||
| 906 | + // rewritten MI before MI; MI itself is erased later, leaving the rewritten | ||
| 907 | + // MI in MI's original position. For a regular STATEPOINT (non-terminator) | ||
| 908 | + // we preserve the original "insert after MI" behavior. | ||
| 909 | + MachineBasicBlock::iterator InsertPt; | ||
| 910 | + if (MI.isTerminator()) | ||
| 911 | + InsertPt = MI.getIterator(); | ||
| 912 | + else | ||
| 913 | + InsertPt = MI.getNextNode(); | ||
| 914 | + MI.getParent()->insert(InsertPt, MIB); | ||
| 904 | return true; | 915 | return true; |
| 905 | } | 916 | } |
| 906 | 917 | ||
| @@ -131,7 +131,7 @@ bool VirtRegAuxInfo::isLiveAtStatepointVarArg(LiveInterval &LI) { | |||
| 131 | return any_of(VRM.getRegInfo().reg_operands(LI.reg()), | 131 | return any_of(VRM.getRegInfo().reg_operands(LI.reg()), |
| 132 | [](MachineOperand &MO) { | 132 | [](MachineOperand &MO) { |
| 133 | MachineInstr *MI = MO.getParent(); | 133 | MachineInstr *MI = MO.getParent(); |
| 134 | - if (MI->getOpcode() != TargetOpcode::STATEPOINT) | 134 | + if (!isStatepointOpcode(MI->getOpcode())) |
| 135 | return false; | 135 | return false; |
| 136 | return StatepointOpers(MI).getVarIdx() <= MI->getOperandNo(&MO); | 136 | return StatepointOpers(MI).getVarIdx() <= MI->getOperandNo(&MO); |
| 137 | }); | 137 | }); |
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | + | ||
| 29 | 30 | ||
| 30 | 31 | ||
| 31 | 32 | ||
| @@ -352,9 +353,8 @@ public: | |||
| 352 | // Invoke statepoint must be last one in block. | 353 | // Invoke statepoint must be last one in block. |
| 353 | bool Last = std::none_of(++MI.getIterator(), MBB->end().getInstrIterator(), | 354 | bool Last = std::none_of(++MI.getIterator(), MBB->end().getInstrIterator(), |
| 354 | [](MachineInstr &I) { | 355 | [](MachineInstr &I) { |
| 355 | - return I.getOpcode() == TargetOpcode::STATEPOINT; | 356 | + return isStatepointOpcode(I.getOpcode()); |
| 356 | }); | 357 | }); |
| 357 | - | ||
| 358 | if (!Last) | 358 | if (!Last) |
| 359 | return; | 359 | return; |
| 360 | 360 | ||
| @@ -616,7 +616,7 @@ bool FixupStatepointCallerSaved::runOnMachineFunction(MachineFunction &MF) { | |||
| 616 | SmallVector<MachineInstr *, 16> Statepoints; | 616 | SmallVector<MachineInstr *, 16> Statepoints; |
| 617 | for (MachineBasicBlock &BB : MF) { | 617 | for (MachineBasicBlock &BB : MF) { |
| 618 | for (MachineInstr &I : BB) { | 618 | for (MachineInstr &I : BB) { |
| 619 | - if (I.getOpcode() == TargetOpcode::STATEPOINT) { | 619 | + if (isStatepointOpcode(I.getOpcode())) { |
| 620 | StatepointOpers SO(&I); | 620 | StatepointOpers SO(&I); |
| 621 | if (!SO.isCJStackCheck()) | 621 | if (!SO.isCJStackCheck()) |
| 622 | Statepoints.push_back(&I); | 622 | Statepoints.push_back(&I); |
| @@ -547,7 +547,7 @@ bool InlineSpiller::canGuaranteeAssignmentAfterRemat(Register VReg, | |||
| 547 | // At the moment, we only handle this for STATEPOINTs since they're the only | 547 | // At the moment, we only handle this for STATEPOINTs since they're the only |
| 548 | // pseudo op where we've seen this. If we start seeing other instructions | 548 | // pseudo op where we've seen this. If we start seeing other instructions |
| 549 | // with the same problem, we need to revisit this. | 549 | // with the same problem, we need to revisit this. |
| 550 | - if (MI.getOpcode() != TargetOpcode::STATEPOINT) | 550 | + if (!isStatepointOpcode(MI.getOpcode())) |
| 551 | return true; | 551 | return true; |
| 552 | // For STATEPOINTs we allow re-materialization for fixed arguments only hoping | 552 | // For STATEPOINTs we allow re-materialization for fixed arguments only hoping |
| 553 | // that number of physical registers is enough to cover all fixed arguments. | 553 | // that number of physical registers is enough to cover all fixed arguments. |
| @@ -818,12 +818,12 @@ foldMemoryOperand(ArrayRef<std::pair<MachineInstr *, unsigned>> Ops, | |||
| 818 | // For that to work we need to untie def and use to pass it through | 818 | // For that to work we need to untie def and use to pass it through |
| 819 | // foldMemoryOperand and signal foldPatchpoint that it is allowed to | 819 | // foldMemoryOperand and signal foldPatchpoint that it is allowed to |
| 820 | // fold them. | 820 | // fold them. |
| 821 | - bool UntieRegs = MI->getOpcode() == TargetOpcode::STATEPOINT; | 821 | + bool UntieRegs = isStatepointOpcode(MI->getOpcode()); |
| 822 | 822 | ||
| 823 | // Spill subregs if the target allows it. | 823 | // Spill subregs if the target allows it. |
| 824 | // We always want to spill subregs for stackmap/patchpoint pseudos. | 824 | // We always want to spill subregs for stackmap/patchpoint pseudos. |
| 825 | bool SpillSubRegs = TII.isSubregFoldable() || | 825 | bool SpillSubRegs = TII.isSubregFoldable() || |
| 826 | - MI->getOpcode() == TargetOpcode::STATEPOINT || | 826 | + isStatepointOpcode(MI->getOpcode()) || |
| 827 | MI->getOpcode() == TargetOpcode::PATCHPOINT || | 827 | MI->getOpcode() == TargetOpcode::PATCHPOINT || |
| 828 | MI->getOpcode() == TargetOpcode::STACKMAP; | 828 | MI->getOpcode() == TargetOpcode::STACKMAP; |
| 829 | 829 | ||
| @@ -892,7 +892,7 @@ LiveIntervals::addSegmentToEndOfBlock(Register Reg, MachineInstr &startInst) { | |||
| 892 | /// the value is alive on exit from Machine instruction. The example of such | 892 | /// the value is alive on exit from Machine instruction. The example of such |
| 893 | /// use is a deopt value in statepoint instruction. | 893 | /// use is a deopt value in statepoint instruction. |
| 894 | static bool hasLiveThroughUse(const MachineInstr *MI, Register Reg) { | 894 | static bool hasLiveThroughUse(const MachineInstr *MI, Register Reg) { |
| 895 | - if (MI->getOpcode() != TargetOpcode::STATEPOINT) | 895 | + if (!isStatepointOpcode(MI->getOpcode())) |
| 896 | return false; | 896 | return false; |
| 897 | StatepointOpers SO(MI); | 897 | StatepointOpers SO(MI); |
| 898 | if (SO.getFlags() & (uint64_t)StatepointFlags::DeoptLiveIn) | 898 | if (SO.getFlags() & (uint64_t)StatepointFlags::DeoptLiveIn) |
| @@ -313,7 +313,7 @@ bool LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { | |||
| 313 | for (MachineInstr &MI : BB) { | 313 | for (MachineInstr &MI : BB) { |
| 314 | // Debug value, stackmap and patchpoint instructions can't be out of | 314 | // Debug value, stackmap and patchpoint instructions can't be out of |
| 315 | // range, so they don't need any updates. | 315 | // range, so they don't need any updates. |
| 316 | - if (MI.isDebugInstr() || MI.getOpcode() == TargetOpcode::STATEPOINT || | 316 | + if (MI.isDebugInstr() || isStatepointOpcode(MI.getOpcode()) || |
| 317 | MI.getOpcode() == TargetOpcode::STACKMAP || | 317 | MI.getOpcode() == TargetOpcode::STACKMAP || |
| 318 | MI.getOpcode() == TargetOpcode::PATCHPOINT) | 318 | MI.getOpcode() == TargetOpcode::PATCHPOINT) |
| 319 | continue; | 319 | continue; |
| @@ -654,7 +654,7 @@ bool MachineInstr::isCalDerivedPtrInCangjieCopyGC( | |||
| 654 | } | 654 | } |
| 655 | // return true if it's gep from a ref ptr | 655 | // return true if it's gep from a ref ptr |
| 656 | for (auto &U : MRI->use_nodbg_operands(Reg)) { | 656 | for (auto &U : MRI->use_nodbg_operands(Reg)) { |
| 657 | - if (U.getParent()->getOpcode() == TargetOpcode::STATEPOINT) { | 657 | + if (isStatepointOpcode(U.getParent()->getOpcode())) { |
| 658 | return true; | 658 | return true; |
| 659 | } | 659 | } |
| 660 | } | 660 | } |
| @@ -693,6 +693,7 @@ bool MachineInstr::isCandidateForCallSiteEntry(QueryType Type) const { | |||
| 693 | case TargetOpcode::PATCHPOINT: | 693 | case TargetOpcode::PATCHPOINT: |
| 694 | case TargetOpcode::STACKMAP: | 694 | case TargetOpcode::STACKMAP: |
| 695 | case TargetOpcode::STATEPOINT: | 695 | case TargetOpcode::STATEPOINT: |
| 696 | + case TargetOpcode::STATEPOINT_TAIL_CALL: | ||
| 696 | case TargetOpcode::FENTRY_CALL: | 697 | case TargetOpcode::FENTRY_CALL: |
| 697 | return false; | 698 | return false; |
| 698 | } | 699 | } |
| @@ -1093,7 +1094,7 @@ void MachineInstr::tieOperands(unsigned DefIdx, unsigned UseIdx) { | |||
| 1093 | // statepoint tied operands are trivial to match (1-1 reg def with reg use), | 1094 | // statepoint tied operands are trivial to match (1-1 reg def with reg use), |
| 1094 | // but on normal instruction, the tied def must be within the first TiedMax | 1095 | // but on normal instruction, the tied def must be within the first TiedMax |
| 1095 | // operands. | 1096 | // operands. |
| 1096 | - assert((isInlineAsm() || getOpcode() == TargetOpcode::STATEPOINT) && | 1097 | + assert((isInlineAsm() || isStatepointOpcode(getOpcode())) && |
| 1097 | "DefIdx out of range"); | 1098 | "DefIdx out of range"); |
| 1098 | UseMO.TiedTo = TiedMax; | 1099 | UseMO.TiedTo = TiedMax; |
| 1099 | } | 1100 | } |
| @@ -1114,7 +1115,7 @@ unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const { | |||
| 1114 | return MO.TiedTo - 1; | 1115 | return MO.TiedTo - 1; |
| 1115 | 1116 | ||
| 1116 | // Uses on normal instructions can be out of range. | 1117 | // Uses on normal instructions can be out of range. |
| 1117 | - if (!isInlineAsm() && getOpcode() != TargetOpcode::STATEPOINT) { | 1118 | + if (!isInlineAsm() && !isStatepointOpcode(getOpcode())) { |
| 1118 | // Normal tied defs must be in the 0..TiedMax-1 range. | 1119 | // Normal tied defs must be in the 0..TiedMax-1 range. |
| 1119 | if (MO.isUse()) | 1120 | if (MO.isUse()) |
| 1120 | return TiedMax - 1; | 1121 | return TiedMax - 1; |
| @@ -1127,7 +1128,7 @@ unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const { | |||
| 1127 | llvm_unreachable("Can't find tied use"); | 1128 | llvm_unreachable("Can't find tied use"); |
| 1128 | } | 1129 | } |
| 1129 | 1130 | ||
| 1130 | - if (getOpcode() == TargetOpcode::STATEPOINT) { | 1131 | + if (isStatepointOpcode(getOpcode())) { |
| 1131 | // In STATEPOINT defs correspond 1-1 to GC pointer operands passed | 1132 | // In STATEPOINT defs correspond 1-1 to GC pointer operands passed |
| 1132 | // on registers. | 1133 | // on registers. |
| 1133 | StatepointOpers SO(this); | 1134 | StatepointOpers SO(this); |
| @@ -1470,7 +1471,7 @@ void MachineInstr::copyImplicitOps(MachineFunction &MF, | |||
| 1470 | 1471 | ||
| 1471 | bool MachineInstr::hasComplexRegisterTies() const { | 1472 | bool MachineInstr::hasComplexRegisterTies() const { |
| 1472 | const MCInstrDesc &MCID = getDesc(); | 1473 | const MCInstrDesc &MCID = getDesc(); |
| 1473 | - if (MCID.Opcode == TargetOpcode::STATEPOINT) | 1474 | + if (isStatepointOpcode(MCID.Opcode)) |
| 1474 | return true; | 1475 | return true; |
| 1475 | for (unsigned I = 0, E = getNumOperands(); I < E; ++I) { | 1476 | for (unsigned I = 0, E = getNumOperands(); I < E; ++I) { |
| 1476 | const auto &Operand = getOperand(I); | 1477 | const auto &Operand = getOperand(I); |
| @@ -1831,7 +1831,8 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { | |||
| 1831 | } | 1831 | } |
| 1832 | break; | 1832 | break; |
| 1833 | } | 1833 | } |
| 1834 | - case TargetOpcode::STATEPOINT: { | 1834 | + case TargetOpcode::STATEPOINT: |
| 1835 | + case TargetOpcode::STATEPOINT_TAIL_CALL: { | ||
| 1835 | StatepointOpers SO(MI); | 1836 | StatepointOpers SO(MI); |
| 1836 | if (!MI->getOperand(SO.getIDPos()).isImm() || | 1837 | if (!MI->getOperand(SO.getIDPos()).isImm() || |
| 1837 | !MI->getOperand(SO.getNBytesPos()).isImm() || | 1838 | !MI->getOperand(SO.getNBytesPos()).isImm() || |
| @@ -3349,7 +3350,9 @@ void MachineVerifier::verifyStackFrame() { | |||
| 3349 | 3350 | ||
| 3350 | // Make sure a basic block with return ends with zero stack adjustment. | 3351 | // Make sure a basic block with return ends with zero stack adjustment. |
| 3351 | if (!MBB->empty() && MBB->back().isReturn()) { | 3352 | if (!MBB->empty() && MBB->back().isReturn()) { |
| 3352 | - if (BBState.ExitIsSetup) | 3353 | + const bool IsTailCallStatepoint = |
| 3354 | + MBB->back().getOpcode() == TargetOpcode::STATEPOINT_TAIL_CALL; | ||
| 3355 | + if (BBState.ExitIsSetup && !IsTailCallStatepoint) | ||
| 3353 | report("A return block ends with a FrameSetup.", MBB); | 3356 | report("A return block ends with a FrameSetup.", MBB); |
| 3354 | if (BBState.ExitValue) | 3357 | if (BBState.ExitValue) |
| 3355 | report("A return block ends with a nonzero stack adjustment.", MBB); | 3358 | report("A return block ends with a nonzero stack adjustment.", MBB); |
| @@ -1447,7 +1447,7 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &MF, | |||
| 1447 | // implementation other than historical accident. The only | 1447 | // implementation other than historical accident. The only |
| 1448 | // remaining difference is the unconditional use of the stack | 1448 | // remaining difference is the unconditional use of the stack |
| 1449 | // pointer as the base register. | 1449 | // pointer as the base register. |
| 1450 | - if (MI.getOpcode() == TargetOpcode::STATEPOINT) { | 1450 | + if (isStatepointOpcode(MI.getOpcode())) { |
| 1451 | assert((!MI.isDebugValue() || i == 0) && | 1451 | assert((!MI.isDebugValue() || i == 0) && |
| 1452 | "Frame indicies can only appear as the first operand of a " | 1452 | "Frame indicies can only appear as the first operand of a " |
| 1453 | "DBG_VALUE machine instruction"); | 1453 | "DBG_VALUE machine instruction"); |
| @@ -2365,7 +2365,7 @@ RAGreedy::RAGreedyStats RAGreedy::computeStats(MachineBasicBlock &MBB) { | |||
| 2365 | auto isPatchpointInstr = [](const MachineInstr &MI) { | 2365 | auto isPatchpointInstr = [](const MachineInstr &MI) { |
| 2366 | return MI.getOpcode() == TargetOpcode::PATCHPOINT || | 2366 | return MI.getOpcode() == TargetOpcode::PATCHPOINT || |
| 2367 | MI.getOpcode() == TargetOpcode::STACKMAP || | 2367 | MI.getOpcode() == TargetOpcode::STACKMAP || |
| 2368 | - MI.getOpcode() == TargetOpcode::STATEPOINT; | 2368 | + isStatepointOpcode(MI.getOpcode()); |
| 2369 | }; | 2369 | }; |
| 2370 | for (MachineInstr &MI : MBB) { | 2370 | for (MachineInstr &MI : MBB) { |
| 2371 | if (MI.isCopy()) { | 2371 | if (MI.isCopy()) { |
| @@ -199,7 +199,7 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node, | |||
| 199 | bool HasVRegVariadicDefs = !MF->getTarget().usesPhysRegsForValues() && | 199 | bool HasVRegVariadicDefs = !MF->getTarget().usesPhysRegsForValues() && |
| 200 | II.isVariadic() && II.variadicOpsAreDefs(); | 200 | II.isVariadic() && II.variadicOpsAreDefs(); |
| 201 | unsigned NumVRegs = HasVRegVariadicDefs ? NumResults : II.getNumDefs(); | 201 | unsigned NumVRegs = HasVRegVariadicDefs ? NumResults : II.getNumDefs(); |
| 202 | - if (Node->getMachineOpcode() == TargetOpcode::STATEPOINT) | 202 | + if (isStatepointOpcode(Node->getMachineOpcode())) |
| 203 | NumVRegs = NumResults; | 203 | NumVRegs = NumResults; |
| 204 | for (unsigned i = 0; i < NumVRegs; ++i) { | 204 | for (unsigned i = 0; i < NumVRegs; ++i) { |
| 205 | // If the specific node value is only used by a CopyToReg and the dest reg | 205 | // If the specific node value is only used by a CopyToReg and the dest reg |
| @@ -990,7 +990,7 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, | |||
| 990 | NumDefs = NumResults; | 990 | NumDefs = NumResults; |
| 991 | } | 991 | } |
| 992 | ScratchRegs = TLI->getScratchRegisters((CallingConv::ID) CC); | 992 | ScratchRegs = TLI->getScratchRegisters((CallingConv::ID) CC); |
| 993 | - } else if (Opc == TargetOpcode::STATEPOINT) { | 993 | + } else if (isStatepointOpcode(Opc)) { |
| 994 | NumDefs = NumResults; | 994 | NumDefs = NumResults; |
| 995 | } | 995 | } |
| 996 | 996 | ||
| @@ -1114,7 +1114,7 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, | |||
| 1114 | } | 1114 | } |
| 1115 | 1115 | ||
| 1116 | const TargetMachine &TM = MF->getTarget(); | 1116 | const TargetMachine &TM = MF->getTarget(); |
| 1117 | - if (Opc == TargetOpcode::STATEPOINT && | 1117 | + if (isStatepointOpcode(Opc) && |
| 1118 | isAArch64Machine(TM.getTargetTriple()) && CJPipeline) { | 1118 | isAArch64Machine(TM.getTargetTriple()) && CJPipeline) { |
| 1119 | UsedRegs.push_back(TLI->getRegisterByName("LR", LLT(), *MF)); | 1119 | UsedRegs.push_back(TLI->getRegisterByName("LR", LLT(), *MF)); |
| 1120 | } | 1120 | } |
| @@ -1150,7 +1150,7 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, | |||
| 1150 | 1150 | ||
| 1151 | // STATEPOINT is too 'dynamic' to have meaningful machine description. | 1151 | // STATEPOINT is too 'dynamic' to have meaningful machine description. |
| 1152 | // We have to manually tie operands. | 1152 | // We have to manually tie operands. |
| 1153 | - if (Opc == TargetOpcode::STATEPOINT && NumDefs > 0) { | 1153 | + if (isStatepointOpcode(Opc) && NumDefs > 0) { |
| 1154 | assert(!HasPhysRegOuts && "STATEPOINT mishandled"); | 1154 | assert(!HasPhysRegOuts && "STATEPOINT mishandled"); |
| 1155 | MachineInstr *MI = MIB; | 1155 | MachineInstr *MI = MIB; |
| 1156 | unsigned Def = 0; | 1156 | unsigned Def = 0; |
| @@ -423,6 +423,9 @@ public: | |||
| 423 | /// invoke of gc.statepoint. | 423 | /// invoke of gc.statepoint. |
| 424 | const BasicBlock *EHPadBB = nullptr; | 424 | const BasicBlock *EHPadBB = nullptr; |
| 425 | 425 | ||
| 426 | + /// Whether this statepoint represents a tail call. | ||
| 427 | + bool IsTailCall = false; | ||
| 428 | + | ||
| 426 | Function *ActualCalledFunction = nullptr; | 429 | Function *ActualCalledFunction = nullptr; |
| 427 | 430 | ||
| 428 | explicit StatepointLoweringInfo(SelectionDAG &DAG) : CLI(DAG) {} | 431 | explicit StatepointLoweringInfo(SelectionDAG &DAG) : CLI(DAG) {} |
| @@ -22,6 +22,8 @@ | |||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | + | ||
| 26 | + | ||
| 25 | 27 | ||
| 26 | 28 | ||
| 27 | 29 | ||
| @@ -330,10 +332,18 @@ static void reservePreviousStackSlotForValue(const Value *IncomingValue, | |||
| 330 | Builder.StatepointLowering.setLocation(Incoming, Loc); | 332 | Builder.StatepointLowering.setLocation(Incoming, Loc); |
| 331 | } | 333 | } |
| 332 | 334 | ||
| 333 | -/// Extract call from statepoint, lower it and return pointer to the | 335 | +namespace { |
| 334 | -/// call node. Also update NodeMap so that getValue(statepoint) will | 336 | +struct StatepointCallLoweringResult { |
| 335 | -/// reference lowered call result | 337 | + SDValue ReturnValue; |
| 336 | -static std::pair<SDValue, SDNode *> lowerCallFromStatepointLoweringInfo( | 338 | + SDNode *CallNode = nullptr; |
| 339 | + SDNode *CallSeqEnd = nullptr; | ||
| 340 | +}; | ||
| 341 | +} // end anonymous namespace | ||
| 342 | + | ||
| 343 | +/// Extract call from statepoint, lower it and return pointers to the call node | ||
| 344 | +/// and call sequence end. Also update NodeMap so that getValue(statepoint) will | ||
| 345 | +/// reference lowered call result. | ||
| 346 | +static StatepointCallLoweringResult lowerCallFromStatepointLoweringInfo( | ||
| 337 | SelectionDAGBuilder::StatepointLoweringInfo &SI, | 347 | SelectionDAGBuilder::StatepointLoweringInfo &SI, |
| 338 | SelectionDAGBuilder &Builder, SmallVectorImpl<SDValue> &PendingExports) { | 348 | SelectionDAGBuilder &Builder, SmallVectorImpl<SDValue> &PendingExports) { |
| 339 | SDValue ReturnValue, CallEndVal; | 349 | SDValue ReturnValue, CallEndVal; |
| @@ -341,9 +351,8 @@ static std::pair<SDValue, SDNode *> lowerCallFromStatepointLoweringInfo( | |||
| 341 | Builder.lowerInvokable(SI.CLI, SI.EHPadBB); | 351 | Builder.lowerInvokable(SI.CLI, SI.EHPadBB); |
| 342 | SDNode *CallEnd = CallEndVal.getNode(); | 352 | SDNode *CallEnd = CallEndVal.getNode(); |
| 343 | 353 | ||
| 344 | - // Get a call instruction from the call sequence chain. Tail calls are not | 354 | + // Get a call instruction from the call sequence chain. The following code is |
| 345 | - // allowed. The following code is essentially reverse engineering X86's | 355 | + // essentially reverse engineering X86's LowerCallTo. |
| 346 | - // LowerCallTo. | ||
| 347 | // | 356 | // |
| 348 | // We are expecting DAG to have the following form: | 357 | // We are expecting DAG to have the following form: |
| 349 | // | 358 | // |
| @@ -370,7 +379,15 @@ static std::pair<SDValue, SDNode *> lowerCallFromStatepointLoweringInfo( | |||
| 370 | } | 379 | } |
| 371 | 380 | ||
| 372 | assert(CallEnd->getOpcode() == ISD::CALLSEQ_END && "expected!"); | 381 | assert(CallEnd->getOpcode() == ISD::CALLSEQ_END && "expected!"); |
| 373 | - return std::make_pair(ReturnValue, CallEnd->getOperand(0).getNode()); | 382 | + return {ReturnValue, CallEnd->getOperand(0).getNode(), CallEnd}; |
| 383 | +} | ||
| 384 | + | ||
| 385 | +static bool isStatepointTailCallSequenceSafe(SDNode *CallSeqEnd) { | ||
| 386 | + assert(CallSeqEnd->getOpcode() == ISD::CALLSEQ_END && "expected!"); | ||
| 387 | + auto *AdjStackUp = dyn_cast<ConstantSDNode>(CallSeqEnd->getOperand(1)); | ||
| 388 | + auto *CalleePopBytes = dyn_cast<ConstantSDNode>(CallSeqEnd->getOperand(2)); | ||
| 389 | + return AdjStackUp && CalleePopBytes && AdjStackUp->getZExtValue() == 0 && | ||
| 390 | + CalleePopBytes->getZExtValue() == 0; | ||
| 374 | } | 391 | } |
| 375 | 392 | ||
| 376 | static MachineMemOperand* getMachineMemOperand(MachineFunction &MF, | 393 | static MachineMemOperand* getMachineMemOperand(MachineFunction &MF, |
| @@ -933,10 +950,11 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT( | |||
| 933 | SI.CLI.setChain(getRoot()); | 950 | SI.CLI.setChain(getRoot()); |
| 934 | 951 | ||
| 935 | // Get call node, we will replace it later with statepoint | 952 | // Get call node, we will replace it later with statepoint |
| 936 | - SDValue ReturnVal; | 953 | + StatepointCallLoweringResult CallLoweringResult = |
| 937 | - SDNode *CallNode; | ||
| 938 | - std::tie(ReturnVal, CallNode) = | ||
| 939 | lowerCallFromStatepointLoweringInfo(SI, *this, PendingExports); | 954 | lowerCallFromStatepointLoweringInfo(SI, *this, PendingExports); |
| 955 | + SDValue ReturnVal = CallLoweringResult.ReturnValue; | ||
| 956 | + SDNode *CallNode = CallLoweringResult.CallNode; | ||
| 957 | + SDNode *CallSeqEnd = CallLoweringResult.CallSeqEnd; | ||
| 940 | 958 | ||
| 941 | // Construct the actual GC_TRANSITION_START, STATEPOINT, and GC_TRANSITION_END | 959 | // Construct the actual GC_TRANSITION_START, STATEPOINT, and GC_TRANSITION_END |
| 942 | // nodes with all the appropriate arguments and return values. | 960 | // nodes with all the appropriate arguments and return values. |
| @@ -961,6 +979,10 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT( | |||
| 961 | const bool IsGCTransition = | 979 | const bool IsGCTransition = |
| 962 | (SI.StatepointFlags & (uint64_t)StatepointFlags::GCTransition) == | 980 | (SI.StatepointFlags & (uint64_t)StatepointFlags::GCTransition) == |
| 963 | (uint64_t)StatepointFlags::GCTransition; | 981 | (uint64_t)StatepointFlags::GCTransition; |
| 982 | + if (SI.IsTailCall && | ||
| 983 | + (IsGCTransition || !SI.CLI.RetTy->isVoidTy() || !SI.GCRelocates.empty() || | ||
| 984 | + !isStatepointTailCallSequenceSafe(CallSeqEnd))) | ||
| 985 | + SI.IsTailCall = false; | ||
| 964 | if (IsGCTransition) { | 986 | if (IsGCTransition) { |
| 965 | SmallVector<SDValue, 8> TSOps; | 987 | SmallVector<SDValue, 8> TSOps; |
| 966 | 988 | ||
| @@ -1052,8 +1074,10 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT( | |||
| 1052 | NodeTys.push_back(MVT::Glue); | 1074 | NodeTys.push_back(MVT::Glue); |
| 1053 | 1075 | ||
| 1054 | unsigned NumResults = NodeTys.size(); | 1076 | unsigned NumResults = NodeTys.size(); |
| 1077 | + unsigned StatepointOpcode = SI.IsTailCall ? TargetOpcode::STATEPOINT_TAIL_CALL | ||
| 1078 | + : TargetOpcode::STATEPOINT; | ||
| 1055 | MachineSDNode *StatepointMCNode = | 1079 | MachineSDNode *StatepointMCNode = |
| 1056 | - DAG.getMachineNode(TargetOpcode::STATEPOINT, getCurSDLoc(), NodeTys, Ops); | 1080 | + DAG.getMachineNode(StatepointOpcode, getCurSDLoc(), NodeTys, Ops); |
| 1057 | DAG.setNodeMemRefs(StatepointMCNode, MemRefs); | 1081 | DAG.setNodeMemRefs(StatepointMCNode, MemRefs); |
| 1058 | 1082 | ||
| 1059 | // For values lowered to tied-defs, create the virtual registers if used | 1083 | // For values lowered to tied-defs, create the virtual registers if used |
| @@ -1143,8 +1167,13 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT( | |||
| 1143 | unsigned NumSinkValues = SinkNode->getNumValues(); | 1167 | unsigned NumSinkValues = SinkNode->getNumValues(); |
| 1144 | SDValue StatepointValues[2] = {SDValue(SinkNode, NumSinkValues - 2), | 1168 | SDValue StatepointValues[2] = {SDValue(SinkNode, NumSinkValues - 2), |
| 1145 | SDValue(SinkNode, NumSinkValues - 1)}; | 1169 | SDValue(SinkNode, NumSinkValues - 1)}; |
| 1146 | - DAG.ReplaceAllUsesWith(CallNode, StatepointValues); | 1170 | + if (SI.IsTailCall) { |
| 1147 | - // Remove original call node | 1171 | + DAG.ReplaceAllUsesWith(CallSeqEnd, StatepointValues); |
| 1172 | + DAG.DeleteNode(CallSeqEnd); | ||
| 1173 | + } else { | ||
| 1174 | + DAG.ReplaceAllUsesWith(CallNode, StatepointValues); | ||
| 1175 | + } | ||
| 1176 | + // Remove original call node. | ||
| 1148 | DAG.DeleteNode(CallNode); | 1177 | DAG.DeleteNode(CallNode); |
| 1149 | 1178 | ||
| 1150 | // Since we always emit CopyToRegs (even for local relocates), we must | 1179 | // Since we always emit CopyToRegs (even for local relocates), we must |
| @@ -1275,6 +1304,13 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I, | |||
| 1275 | SI.StatepointFlags = I.getFlags(); | 1304 | SI.StatepointFlags = I.getFlags(); |
| 1276 | SI.NumPatchBytes = I.getNumPatchBytes(); | 1305 | SI.NumPatchBytes = I.getNumPatchBytes(); |
| 1277 | SI.EHPadBB = EHPadBB; | 1306 | SI.EHPadBB = EHPadBB; |
| 1307 | + const Triple &TT = DAG.getTarget().getTargetTriple(); | ||
| 1308 | + SI.IsTailCall = | ||
| 1309 | + I.isTailCall() && I.getNumPatchBytes() == 0 && | ||
| 1310 | + (TT.isAArch64() || TT.isX86()) && | ||
| 1311 | + !needToDisableTailCall(I, DAG.getTargetLoweringInfo(), | ||
| 1312 | + I.isMustTailCall()) && | ||
| 1313 | + isInTailCallPosition(I, DAG.getTarget()); | ||
| 1278 | 1314 | ||
| 1279 | SI.ActualCalledFunction = I.getActualCalledFunction(); | 1315 | SI.ActualCalledFunction = I.getActualCalledFunction(); |
| 1280 | 1316 | ||
| @@ -1286,9 +1322,12 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I, | |||
| 1286 | // See: X86FrameLowering.cpp:hasFP() | 1322 | // See: X86FrameLowering.cpp:hasFP() |
| 1287 | DAG.getMachineFunction().getFrameInfo().setHasStackMap(); | 1323 | DAG.getMachineFunction().getFrameInfo().setHasStackMap(); |
| 1288 | } | 1324 | } |
| 1325 | + if (SI.IsTailCall) { | ||
| 1326 | + HasTailCall = true; | ||
| 1327 | + return; | ||
| 1328 | + } | ||
| 1289 | // Export the result value if needed | 1329 | // Export the result value if needed |
| 1290 | const auto GCResultLocality = getGCResultLocality(I); | 1330 | const auto GCResultLocality = getGCResultLocality(I); |
| 1291 | - | ||
| 1292 | if ((!GCResultLocality.first && !GCResultLocality.second) || | 1331 | if ((!GCResultLocality.first && !GCResultLocality.second) || |
| 1293 | (I.getActualReturnType()->isEmptyTy())) { | 1332 | (I.getActualReturnType()->isEmptyTy())) { |
| 1294 | // The return value is not needed, just generate a poison value. | 1333 | // The return value is not needed, just generate a poison value. |
| @@ -121,7 +121,7 @@ InsertPointAnalysis::computeLastInsertPoint(const LiveInterval &CurLI, | |||
| 121 | // in landing pad. So we cannot split interval after statepoint instruction. | 121 | // in landing pad. So we cannot split interval after statepoint instruction. |
| 122 | if (SlotIndex::isSameInstr(VNI->def, LIP.second)) | 122 | if (SlotIndex::isSameInstr(VNI->def, LIP.second)) |
| 123 | if (auto *I = LIS.getInstructionFromIndex(LIP.second)) | 123 | if (auto *I = LIS.getInstructionFromIndex(LIP.second)) |
| 124 | - if (I->getOpcode() == TargetOpcode::STATEPOINT) | 124 | + if (isStatepointOpcode(I->getOpcode())) |
| 125 | return LIP.second; | 125 | return LIP.second; |
| 126 | 126 | ||
| 127 | // If the value leaving MBB was defined after the call in MBB, it can't | 127 | // If the value leaving MBB was defined after the call in MBB, it can't |
| @@ -177,7 +177,7 @@ void SplitAnalysis::analyzeUses() { | |||
| 177 | // We don't want to split in the statepiont instruction point, | 177 | // We don't want to split in the statepiont instruction point, |
| 178 | // so we don't put it in the UseSlots here. | 178 | // so we don't put it in the UseSlots here. |
| 179 | if (!MO.isUndef() && | 179 | if (!MO.isUndef() && |
| 180 | - MO.getParent()->getOpcode() != TargetOpcode::STATEPOINT) { | 180 | + !isStatepointOpcode(MO.getParent()->getOpcode())) { |
| 181 | UseSlots.push_back(LIS.getInstructionIndex(*MO.getParent()).getRegSlot()); | 181 | UseSlots.push_back(LIS.getInstructionIndex(*MO.getParent()).getRegSlot()); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| @@ -230,8 +230,8 @@ void SplitAnalysis::calcLiveBlockInfo() { | |||
| 230 | if (LVI->end < Stop) { | 230 | if (LVI->end < Stop) { |
| 231 | // The range shouldn't end mid-block if there are no uses and don`t | 231 | // The range shouldn't end mid-block if there are no uses and don`t |
| 232 | // end in statepoint. This shouldn't happen. | 232 | // end in statepoint. This shouldn't happen. |
| 233 | - if (LIS.getInstructionFromIndex(LVI->end)->getOpcode() != | 233 | + if (!isStatepointOpcode( |
| 234 | - TargetOpcode::STATEPOINT) { | 234 | + LIS.getInstructionFromIndex(LVI->end)->getOpcode())) { |
| 235 | llvm_unreachable("range ends mid block with no uses"); | 235 | llvm_unreachable("range ends mid block with no uses"); |
| 236 | return; | 236 | return; |
| 237 | } | 237 | } |
| @@ -925,7 +925,7 @@ void StackMaps::recordStackMapOpers(const MCSymbol &MILabel, | |||
| 925 | } | 925 | } |
| 926 | 926 | ||
| 927 | // Parse operands. | 927 | // Parse operands. |
| 928 | - if (MI.getOpcode() == TargetOpcode::STATEPOINT) | 928 | + if (isStatepointOpcode(MI.getOpcode())) |
| 929 | parseStatepointOpers(MI, OpersInfo.MOI, OpersInfo.MOE, CSInfo); | 929 | parseStatepointOpers(MI, OpersInfo.MOI, OpersInfo.MOE, CSInfo); |
| 930 | else | 930 | else |
| 931 | while (OpersInfo.MOI != OpersInfo.MOE) | 931 | while (OpersInfo.MOI != OpersInfo.MOE) |
| @@ -960,7 +960,7 @@ void StackMaps::recordStackMapOpers(const MCSymbol &MILabel, | |||
| 960 | 960 | ||
| 961 | // get Line number from debug info | 961 | // get Line number from debug info |
| 962 | uint32_t Line = 0; | 962 | uint32_t Line = 0; |
| 963 | - if (MI.getOpcode() == TargetOpcode::STATEPOINT) { | 963 | + if (isStatepointOpcode(MI.getOpcode())) { |
| 964 | if (OpersInfo.ID == Cangjie::CJStatepointID::StackCheck && | 964 | if (OpersInfo.ID == Cangjie::CJStatepointID::StackCheck && |
| 965 | MI.getMF()->getFunction().getSubprogram() != nullptr) { | 965 | MI.getMF()->getFunction().getSubprogram() != nullptr) { |
| 966 | Line = MI.getMF()->getFunction().getSubprogram()->getLine(); | 966 | Line = MI.getMF()->getFunction().getSubprogram()->getLine(); |
| @@ -1015,7 +1015,7 @@ void StackMaps::recordPatchPoint(const MCSymbol &L, const MachineInstr &MI) { | |||
| 1015 | void StackMaps::recordStatepoint(const MCSymbol &L, const MachineInstr &MI, | 1015 | void StackMaps::recordStatepoint(const MCSymbol &L, const MachineInstr &MI, |
| 1016 | bool RecordAllRefInReg) { | 1016 | bool RecordAllRefInReg) { |
| 1017 | StackMapOpersInfo OpersInfo; | 1017 | StackMapOpersInfo OpersInfo; |
| 1018 | - if (MI.getOpcode() == TargetOpcode::STATEPOINT) { | 1018 | + if (isStatepointOpcode(MI.getOpcode())) { |
| 1019 | // Record all the deopt and gc operands (they're contiguous and run from the | 1019 | // Record all the deopt and gc operands (they're contiguous and run from the |
| 1020 | // initial index to the end of the operand list) | 1020 | // initial index to the end of the operand list) |
| 1021 | StatepointOpers opers(&MI); | 1021 | StatepointOpers opers(&MI); |
| @@ -1471,9 +1471,7 @@ static void genStackMapInfo(CompressedInfo &Data, | |||
| 1471 | if (IsAllIdxsInvalid) { | 1471 | if (IsAllIdxsInvalid) { |
| 1472 | IdxInfo.DerivedInfoStartIdx = 0; | 1472 | IdxInfo.DerivedInfoStartIdx = 0; |
| 1473 | } else { | 1473 | } else { |
| 1474 | - IdxInfo.DerivedInfoStartIdx = Data.DerivedInfo.size(); | 1474 | + IdxInfo.DerivedInfoStartIdx = Data.getOrInsertDerivedInfoStartIdx(IdxsInfo); |
| 1475 | - Data.DerivedInfo.insert(Data.DerivedInfo.end(), IdxsInfo.begin(), | ||
| 1476 | - IdxsInfo.end()); | ||
| 1477 | } | 1475 | } |
| 1478 | 1476 | ||
| 1479 | if (EnableStackGrow) { | 1477 | if (EnableStackGrow) { |
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | + | ||
| 20 | 21 | ||
| 21 | 22 | ||
| 22 | 23 | ||
| @@ -183,7 +184,7 @@ MachineBasicBlock::iterator TargetFrameLowering::preCJStackCheck( | |||
| 183 | 184 | ||
| 184 | for (auto BBI = MF.front().begin(); BBI != MF.front().end(); BBI++) { | 185 | for (auto BBI = MF.front().begin(); BBI != MF.front().end(); BBI++) { |
| 185 | MachineInstr *MI = &*BBI; | 186 | MachineInstr *MI = &*BBI; |
| 186 | - if (MI->getOpcode() != TargetOpcode::STATEPOINT) | 187 | + if (!isStatepointOpcode(MI->getOpcode())) |
| 187 | continue; | 188 | continue; |
| 188 | 189 | ||
| 189 | StatepointOpers SO(MI); | 190 | StatepointOpers SO(MI); |
| @@ -483,6 +483,7 @@ TargetInstrInfo::getPatchpointUnfoldableRange(const MachineInstr &MI) const { | |||
| 483 | // stackmap e.g. via anyregcc). | 483 | // stackmap e.g. via anyregcc). |
| 484 | return std::make_pair(0, PatchPointOpers(&MI).getVarIdx()); | 484 | return std::make_pair(0, PatchPointOpers(&MI).getVarIdx()); |
| 485 | case TargetOpcode::STATEPOINT: | 485 | case TargetOpcode::STATEPOINT: |
| 486 | + case TargetOpcode::STATEPOINT_TAIL_CALL: | ||
| 486 | // For statepoints, fold deopt and gc arguments, but not call arguments. | 487 | // For statepoints, fold deopt and gc arguments, but not call arguments. |
| 487 | return std::make_pair(MI.getNumDefs(), StatepointOpers(&MI).getVarIdx()); | 488 | return std::make_pair(MI.getNumDefs(), StatepointOpers(&MI).getVarIdx()); |
| 488 | default: | 489 | default: |
| @@ -597,7 +598,7 @@ MachineInstr *TargetInstrInfo::foldMemoryOperand(MachineInstr &MI, | |||
| 597 | 598 | ||
| 598 | if (MI.getOpcode() == TargetOpcode::STACKMAP || | 599 | if (MI.getOpcode() == TargetOpcode::STACKMAP || |
| 599 | MI.getOpcode() == TargetOpcode::PATCHPOINT || | 600 | MI.getOpcode() == TargetOpcode::PATCHPOINT || |
| 600 | - MI.getOpcode() == TargetOpcode::STATEPOINT) { | 601 | + isStatepointOpcode(MI.getOpcode())) { |
| 601 | // Fold stackmap/patchpoint. | 602 | // Fold stackmap/patchpoint. |
| 602 | NewMI = foldPatchpoint(MF, MI, Ops, FI, *this); | 603 | NewMI = foldPatchpoint(MF, MI, Ops, FI, *this); |
| 603 | if (NewMI) | 604 | if (NewMI) |
| @@ -666,7 +667,7 @@ MachineInstr *TargetInstrInfo::foldMemoryOperand(MachineInstr &MI, | |||
| 666 | 667 | ||
| 667 | if ((MI.getOpcode() == TargetOpcode::STACKMAP || | 668 | if ((MI.getOpcode() == TargetOpcode::STACKMAP || |
| 668 | MI.getOpcode() == TargetOpcode::PATCHPOINT || | 669 | MI.getOpcode() == TargetOpcode::PATCHPOINT || |
| 669 | - MI.getOpcode() == TargetOpcode::STATEPOINT) && | 670 | + isStatepointOpcode(MI.getOpcode())) && |
| 670 | isLoadFromStackSlot(LoadMI, FrameIndex)) { | 671 | isLoadFromStackSlot(LoadMI, FrameIndex)) { |
| 671 | // Fold stackmap/patchpoint. | 672 | // Fold stackmap/patchpoint. |
| 672 | NewMI = foldPatchpoint(MF, MI, Ops, FrameIndex, *this); | 673 | NewMI = foldPatchpoint(MF, MI, Ops, FrameIndex, *this); |
| @@ -1207,7 +1207,7 @@ TargetLoweringBase::emitPatchPoint(MachineInstr &InitialMI, | |||
| 1207 | // Used for spills inserted by StatepointLowering. This codepath is not | 1207 | // Used for spills inserted by StatepointLowering. This codepath is not |
| 1208 | // used for patchpoints/stackmaps at all, for these spilling is done via | 1208 | // used for patchpoints/stackmaps at all, for these spilling is done via |
| 1209 | // foldMemoryOperand callback only. | 1209 | // foldMemoryOperand callback only. |
| 1210 | - assert(MI->getOpcode() == TargetOpcode::STATEPOINT && "sanity"); | 1210 | + assert(isStatepointOpcode(MI->getOpcode()) && "sanity"); |
| 1211 | MIB.addImm(StackMaps::IndirectMemRefOp); | 1211 | MIB.addImm(StackMaps::IndirectMemRefOp); |
| 1212 | MIB.addImm(MFI.getObjectSize(FI)); | 1212 | MIB.addImm(MFI.getObjectSize(FI)); |
| 1213 | MIB.add(MO); | 1213 | MIB.add(MO); |
| @@ -1228,7 +1228,7 @@ TargetLoweringBase::emitPatchPoint(MachineInstr &InitialMI, | |||
| 1228 | 1228 | ||
| 1229 | // Note: STATEPOINT MMOs are added during SelectionDAG. STACKMAP, and | 1229 | // Note: STATEPOINT MMOs are added during SelectionDAG. STACKMAP, and |
| 1230 | // PATCHPOINT should be updated to do the same. (TODO) | 1230 | // PATCHPOINT should be updated to do the same. (TODO) |
| 1231 | - if (MI->getOpcode() != TargetOpcode::STATEPOINT) { | 1231 | + if (!isStatepointOpcode(MI->getOpcode())) { |
| 1232 | auto Flags = MachineMemOperand::MOLoad; | 1232 | auto Flags = MachineMemOperand::MOLoad; |
| 1233 | MachineMemOperand *MMO = MF.getMachineMemOperand( | 1233 | MachineMemOperand *MMO = MF.getMachineMemOperand( |
| 1234 | MachinePointerInfo::getFixedStack(MF, FI), Flags, | 1234 | MachinePointerInfo::getFixedStack(MF, FI), Flags, |
| @@ -1813,7 +1813,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &Func) { | |||
| 1813 | } | 1813 | } |
| 1814 | } | 1814 | } |
| 1815 | 1815 | ||
| 1816 | - if (mi->getOpcode() == TargetOpcode::STATEPOINT && | 1816 | + if (isStatepointOpcode(mi->getOpcode()) && |
| 1817 | processStatepoint(&*mi, TiedOperands)) { | 1817 | processStatepoint(&*mi, TiedOperands)) { |
| 1818 | TiedOperands.clear(); | 1818 | TiedOperands.clear(); |
| 1819 | LLVM_DEBUG(dbgs() << "\t\trewrite to:\t" << *mi); | 1819 | LLVM_DEBUG(dbgs() << "\t\trewrite to:\t" << *mi); |
| @@ -41,6 +41,7 @@ | |||
| 41 | 41 | ||
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | + | ||
| 44 | 45 | ||
| 45 | 46 | ||
| 46 | 47 | ||
| @@ -1357,6 +1358,8 @@ void AArch64AsmPrinter::emitGcStateCheck() { | |||
| 1357 | void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, | 1358 | void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, |
| 1358 | const MachineInstr &MI) { | 1359 | const MachineInstr &MI) { |
| 1359 | StatepointOpers SOpers(&MI); | 1360 | StatepointOpers SOpers(&MI); |
| 1361 | + const bool IsTailCallStatepoint = | ||
| 1362 | + MI.getOpcode() == TargetOpcode::STATEPOINT_TAIL_CALL; | ||
| 1360 | // Lower call target and choose correct opcode | 1363 | // Lower call target and choose correct opcode |
| 1361 | const MachineOperand &CallTarget = SOpers.getCallTarget(); | 1364 | const MachineOperand &CallTarget = SOpers.getCallTarget(); |
| 1362 | if (CJPipeline) { | 1365 | if (CJPipeline) { |
| @@ -1377,6 +1380,8 @@ void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, | |||
| 1377 | } | 1380 | } |
| 1378 | 1381 | ||
| 1379 | if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { | 1382 | if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { |
| 1383 | + assert(!IsTailCallStatepoint && | ||
| 1384 | + "tail call statepoint cannot request patch bytes"); | ||
| 1380 | // 4: size of the patchpoint intrinsic | 1385 | // 4: size of the patchpoint intrinsic |
| 1381 | assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested"); | 1386 | assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested"); |
| 1382 | for (unsigned i = 0; i < PatchBytes; i += 4) | 1387 | for (unsigned i = 0; i < PatchBytes; i += 4) |
| @@ -1387,8 +1392,11 @@ void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, | |||
| 1387 | switch (CallTarget.getType()) { | 1392 | switch (CallTarget.getType()) { |
| 1388 | case MachineOperand::MO_GlobalAddress: | 1393 | case MachineOperand::MO_GlobalAddress: |
| 1389 | case MachineOperand::MO_ExternalSymbol: { | 1394 | case MachineOperand::MO_ExternalSymbol: { |
| 1390 | - CallOpcode = AArch64::BL; | 1395 | + CallOpcode = IsTailCallStatepoint ? AArch64::B : AArch64::BL; |
| 1391 | - if (tryEmitCangjieSpecificCallByMOSym(&MI, CallTarget, CallOpcode)) { | 1396 | + unsigned CangjieCallOpcode = |
| 1397 | + IsTailCallStatepoint ? AArch64::TCRETURNdi : CallOpcode; | ||
| 1398 | + if (tryEmitCangjieSpecificCallByMOSym(&MI, CallTarget, | ||
| 1399 | + CangjieCallOpcode)) { | ||
| 1392 | SM.recordCJStackMap(MI); | 1400 | SM.recordCJStackMap(MI); |
| 1393 | return; | 1401 | return; |
| 1394 | } | 1402 | } |
| @@ -1397,11 +1405,11 @@ void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, | |||
| 1397 | } | 1405 | } |
| 1398 | case MachineOperand::MO_Immediate: | 1406 | case MachineOperand::MO_Immediate: |
| 1399 | CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); | 1407 | CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); |
| 1400 | - CallOpcode = AArch64::BL; | 1408 | + CallOpcode = IsTailCallStatepoint ? AArch64::B : AArch64::BL; |
| 1401 | break; | 1409 | break; |
| 1402 | case MachineOperand::MO_Register: | 1410 | case MachineOperand::MO_Register: |
| 1403 | CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); | 1411 | CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); |
| 1404 | - CallOpcode = AArch64::BLR; | 1412 | + CallOpcode = IsTailCallStatepoint ? AArch64::BR : AArch64::BLR; |
| 1405 | break; | 1413 | break; |
| 1406 | default: | 1414 | default: |
| 1407 | llvm_unreachable("Unsupported operand type in statepoint call target"); | 1415 | llvm_unreachable("Unsupported operand type in statepoint call target"); |
| @@ -1818,6 +1826,7 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { | |||
| 1818 | return LowerPATCHPOINT(*OutStreamer, SM, *MI); | 1826 | return LowerPATCHPOINT(*OutStreamer, SM, *MI); |
| 1819 | 1827 | ||
| 1820 | case TargetOpcode::STATEPOINT: | 1828 | case TargetOpcode::STATEPOINT: |
| 1829 | + case TargetOpcode::STATEPOINT_TAIL_CALL: | ||
| 1821 | return LowerSTATEPOINT(*OutStreamer, SM, *MI); | 1830 | return LowerSTATEPOINT(*OutStreamer, SM, *MI); |
| 1822 | 1831 | ||
| 1823 | case TargetOpcode::FAULTING_OP: | 1832 | case TargetOpcode::FAULTING_OP: |
| @@ -2157,7 +2166,7 @@ void AArch64AsmPrinter::emitCJThrowException(const MachineInstr *MI, | |||
| 2157 | // .LNewArrayFin | 2166 | // .LNewArrayFin |
| 2158 | void AArch64AsmPrinter::emitCJNewArrayFastPath(const MachineInstr &MI, | 2167 | void AArch64AsmPrinter::emitCJNewArrayFastPath(const MachineInstr &MI, |
| 2159 | const MachineOperand &MOSym) { | 2168 | const MachineOperand &MOSym) { |
| 2160 | - if (MI.getOpcode() != TargetOpcode::STATEPOINT) { | 2169 | + if (!isStatepointOpcode(MI.getOpcode())) { |
| 2161 | report_fatal_error("New Obj Must be in Statepoint"); | 2170 | report_fatal_error("New Obj Must be in Statepoint"); |
| 2162 | } | 2171 | } |
| 2163 | using namespace AArch64; | 2172 | using namespace AArch64; |
| @@ -2521,6 +2521,7 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( | |||
| 2521 | return EmitF128CSEL(MI, BB); | 2521 | return EmitF128CSEL(MI, BB); |
| 2522 | 2522 | ||
| 2523 | case TargetOpcode::STATEPOINT: | 2523 | case TargetOpcode::STATEPOINT: |
| 2524 | + case TargetOpcode::STATEPOINT_TAIL_CALL: | ||
| 2524 | // STATEPOINT is a pseudo instruction which has no implicit defs/uses | 2525 | // STATEPOINT is a pseudo instruction which has no implicit defs/uses |
| 2525 | // while bl call instruction (where statepoint will be lowered at the end) | 2526 | // while bl call instruction (where statepoint will be lowered at the end) |
| 2526 | // has implicit def. This def is early-clobber as it will be set at | 2527 | // has implicit def. This def is early-clobber as it will be set at |
| @@ -28,6 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | + | ||
| 31 | 32 | ||
| 32 | 33 | ||
| 33 | 34 | ||
| @@ -85,7 +86,7 @@ unsigned AArch64InstrInfo::getCangjieSpecificCallInstSizeInBytes( | |||
| 85 | return 0; | 86 | return 0; |
| 86 | } | 87 | } |
| 87 | const MachineOperand *MOSym = nullptr; | 88 | const MachineOperand *MOSym = nullptr; |
| 88 | - if (MI.getOpcode() == TargetOpcode::STATEPOINT) { | 89 | + if (isStatepointOpcode(MI.getOpcode())) { |
| 89 | StatepointOpers SO(&MI); | 90 | StatepointOpers SO(&MI); |
| 90 | if (SO.getID() == Cangjie::CJStatepointID::NewArrayFast) { | 91 | if (SO.getID() == Cangjie::CJStatepointID::NewArrayFast) { |
| 91 | return 52; // 52: 52 bytes(13 insts) for new array call | 92 | return 52; // 52: 52 bytes(13 insts) for new array call |
| @@ -187,6 +188,7 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { | |||
| 187 | assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); | 188 | assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); |
| 188 | break; | 189 | break; |
| 189 | case TargetOpcode::STATEPOINT: | 190 | case TargetOpcode::STATEPOINT: |
| 191 | + case TargetOpcode::STATEPOINT_TAIL_CALL: | ||
| 190 | NumBytes = StatepointOpers(&MI).getNumPatchBytes(); | 192 | NumBytes = StatepointOpers(&MI).getNumPatchBytes(); |
| 191 | assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); | 193 | assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); |
| 192 | // No patch bytes means a normal call inst is emitted | 194 | // No patch bytes means a normal call inst is emitted |
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | + | ||
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | 31 | ||
| @@ -751,7 +752,7 @@ void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, | |||
| 751 | // Special handling of dbg_value, stackmap patchpoint statepoint instructions. | 752 | // Special handling of dbg_value, stackmap patchpoint statepoint instructions. |
| 752 | if (MI.getOpcode() == TargetOpcode::STACKMAP || | 753 | if (MI.getOpcode() == TargetOpcode::STACKMAP || |
| 753 | MI.getOpcode() == TargetOpcode::PATCHPOINT || | 754 | MI.getOpcode() == TargetOpcode::PATCHPOINT || |
| 754 | - MI.getOpcode() == TargetOpcode::STATEPOINT) { | 755 | + isStatepointOpcode(MI.getOpcode())) { |
| 755 | StackOffset Offset = | 756 | StackOffset Offset = |
| 756 | TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, | 757 | TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, |
| 757 | /*PreferFP=*/true, | 758 | /*PreferFP=*/true, |
| @@ -36484,6 +36484,7 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, | |||
| 36484 | return EmitSjLjDispatchBlock(MI, BB); | 36484 | return EmitSjLjDispatchBlock(MI, BB); |
| 36485 | 36485 | ||
| 36486 | case TargetOpcode::STATEPOINT: | 36486 | case TargetOpcode::STATEPOINT: |
| 36487 | + case TargetOpcode::STATEPOINT_TAIL_CALL: | ||
| 36487 | // As an implementation detail, STATEPOINT shares the STACKMAP format at | 36488 | // As an implementation detail, STATEPOINT shares the STACKMAP format at |
| 36488 | // this point in the process. We diverge later. | 36489 | // this point in the process. We diverge later. |
| 36489 | return emitPatchPoint(MI, BB); | 36490 | return emitPatchPoint(MI, BB); |
| @@ -31,6 +31,7 @@ | |||
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | 33 | ||
| 34 | + | ||
| 34 | 35 | ||
| 35 | 36 | ||
| 36 | 37 | ||
| @@ -1588,6 +1589,8 @@ void X86AsmPrinter::LowerSTATEPOINT(const MachineInstr &MI, | |||
| 1588 | 1589 | ||
| 1589 | NoAutoPaddingScope NoPadScope(*OutStreamer); | 1590 | NoAutoPaddingScope NoPadScope(*OutStreamer); |
| 1590 | StatepointOpers SOpers(&MI); | 1591 | StatepointOpers SOpers(&MI); |
| 1592 | + const bool IsTailCallStatepoint = | ||
| 1593 | + MI.getOpcode() == TargetOpcode::STATEPOINT_TAIL_CALL; | ||
| 1591 | // Lower call target and choose correct opcode | 1594 | // Lower call target and choose correct opcode |
| 1592 | const MachineOperand &CallTarget = SOpers.getCallTarget(); | 1595 | const MachineOperand &CallTarget = SOpers.getCallTarget(); |
| 1593 | if (CJPipeline) { | 1596 | if (CJPipeline) { |
| @@ -1608,6 +1611,8 @@ void X86AsmPrinter::LowerSTATEPOINT(const MachineInstr &MI, | |||
| 1608 | } | 1611 | } |
| 1609 | 1612 | ||
| 1610 | if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { | 1613 | if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { |
| 1614 | + assert(!IsTailCallStatepoint && | ||
| 1615 | + "tail call statepoint cannot request patch bytes"); | ||
| 1611 | emitX86Nops(*OutStreamer, PatchBytes, Subtarget); | 1616 | emitX86Nops(*OutStreamer, PatchBytes, Subtarget); |
| 1612 | } else { | 1617 | } else { |
| 1613 | MCOperand CallTargetMCOp; | 1618 | MCOperand CallTargetMCOp; |
| @@ -1617,10 +1622,13 @@ void X86AsmPrinter::LowerSTATEPOINT(const MachineInstr &MI, | |||
| 1617 | case MachineOperand::MO_ExternalSymbol: { | 1622 | case MachineOperand::MO_ExternalSymbol: { |
| 1618 | CallTargetMCOp = MCIL.LowerSymbolOperand( | 1623 | CallTargetMCOp = MCIL.LowerSymbolOperand( |
| 1619 | CallTarget, MCIL.GetSymbolFromOperand(CallTarget)); | 1624 | CallTarget, MCIL.GetSymbolFromOperand(CallTarget)); |
| 1620 | - CallOpcode = X86::CALL64pcrel32; | 1625 | + CallOpcode = |
| 1626 | + IsTailCallStatepoint ? X86::TAILJMPd64 : X86::CALL64pcrel32; | ||
| 1621 | if (tryEmitCangjieSpecificCallByMOSym(&MI, CallTarget, CallOpcode)) { | 1627 | if (tryEmitCangjieSpecificCallByMOSym(&MI, CallTarget, CallOpcode)) { |
| 1622 | return; | 1628 | return; |
| 1623 | } | 1629 | } |
| 1630 | + CallOpcode = IsTailCallStatepoint ? convertTailJumpOpcode(CallOpcode) | ||
| 1631 | + : CallOpcode; | ||
| 1624 | // Currently, we only support relative addressing with statepoints. | 1632 | // Currently, we only support relative addressing with statepoints. |
| 1625 | // Otherwise, we'll need a scratch register to hold the target | 1633 | // Otherwise, we'll need a scratch register to hold the target |
| 1626 | // address. You'll fail asserts during load & relocation if this | 1634 | // address. You'll fail asserts during load & relocation if this |
| @@ -1629,7 +1637,8 @@ void X86AsmPrinter::LowerSTATEPOINT(const MachineInstr &MI, | |||
| 1629 | } | 1637 | } |
| 1630 | case MachineOperand::MO_Immediate: | 1638 | case MachineOperand::MO_Immediate: |
| 1631 | CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); | 1639 | CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); |
| 1632 | - CallOpcode = X86::CALL64pcrel32; | 1640 | + CallOpcode = IsTailCallStatepoint ? convertTailJumpOpcode(X86::TAILJMPd64) |
| 1641 | + : X86::CALL64pcrel32; | ||
| 1633 | // Currently, we only support relative addressing with statepoints. | 1642 | // Currently, we only support relative addressing with statepoints. |
| 1634 | // Otherwise, we'll need a scratch register to hold the target | 1643 | // Otherwise, we'll need a scratch register to hold the target |
| 1635 | // immediate. You'll fail asserts during load & relocation if this | 1644 | // immediate. You'll fail asserts during load & relocation if this |
| @@ -1641,7 +1650,7 @@ void X86AsmPrinter::LowerSTATEPOINT(const MachineInstr &MI, | |||
| 1641 | report_fatal_error("Lowering register statepoints with thunks not " | 1650 | report_fatal_error("Lowering register statepoints with thunks not " |
| 1642 | "yet implemented."); | 1651 | "yet implemented."); |
| 1643 | CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); | 1652 | CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); |
| 1644 | - CallOpcode = X86::CALL64r; | 1653 | + CallOpcode = IsTailCallStatepoint ? X86::JMP64r : X86::CALL64r; |
| 1645 | break; | 1654 | break; |
| 1646 | default: | 1655 | default: |
| 1647 | llvm_unreachable("Unsupported operand type in statepoint call target"); | 1656 | llvm_unreachable("Unsupported operand type in statepoint call target"); |
| @@ -1652,6 +1661,9 @@ void X86AsmPrinter::LowerSTATEPOINT(const MachineInstr &MI, | |||
| 1652 | MCInst CallInst; | 1661 | MCInst CallInst; |
| 1653 | CallInst.setOpcode(CallOpcode); | 1662 | CallInst.setOpcode(CallOpcode); |
| 1654 | CallInst.addOperand(CallTargetMCOp); | 1663 | CallInst.addOperand(CallTargetMCOp); |
| 1664 | + if (IsTailCallStatepoint) { | ||
| 1665 | + OutStreamer->AddComment("TAILCALL"); | ||
| 1666 | + } | ||
| 1655 | OutStreamer->emitInstruction(CallInst, getSubtargetInfo()); | 1667 | OutStreamer->emitInstruction(CallInst, getSubtargetInfo()); |
| 1656 | } | 1668 | } |
| 1657 | 1669 | ||
| @@ -2804,7 +2816,7 @@ void X86AsmPrinter::tryDoAdaptionForFP16InCJ(const MachineInstr *MI, | |||
| 2804 | } | 2816 | } |
| 2805 | 2817 | ||
| 2806 | unsigned Opcode = MI->getOpcode(); | 2818 | unsigned Opcode = MI->getOpcode(); |
| 2807 | - if (Opcode == TargetOpcode::STATEPOINT) { | 2819 | + if (isStatepointOpcode(Opcode)) { |
| 2808 | return; | 2820 | return; |
| 2809 | } | 2821 | } |
| 2810 | 2822 | ||
| @@ -3074,6 +3086,7 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) { | |||
| 3074 | return; | 3086 | return; |
| 3075 | } | 3087 | } |
| 3076 | case TargetOpcode::STATEPOINT: | 3088 | case TargetOpcode::STATEPOINT: |
| 3089 | + case TargetOpcode::STATEPOINT_TAIL_CALL: | ||
| 3077 | return LowerSTATEPOINT(*MI, MCInstLowering); | 3090 | return LowerSTATEPOINT(*MI, MCInstLowering); |
| 3078 | 3091 | ||
| 3079 | case TargetOpcode::FAULTING_OP: | 3092 | case TargetOpcode::FAULTING_OP: |
| @@ -3439,7 +3452,7 @@ void X86AsmPrinter::emitCJThrowException(const MachineInstr *MI, | |||
| 3439 | // LNewArrayFin | 3452 | // LNewArrayFin |
| 3440 | void X86AsmPrinter::emitCJNewArrayFastPath(const MachineInstr &MI, | 3453 | void X86AsmPrinter::emitCJNewArrayFastPath(const MachineInstr &MI, |
| 3441 | const MachineOperand &MOSym) { | 3454 | const MachineOperand &MOSym) { |
| 3442 | - if (MI.getOpcode() != TargetOpcode::STATEPOINT) { | 3455 | + if (!isStatepointOpcode(MI.getOpcode())) { |
| 3443 | report_fatal_error("New Array Must be in Statepoint"); | 3456 | report_fatal_error("New Array Must be in Statepoint"); |
| 3444 | } | 3457 | } |
| 3445 | 3458 | ||
| @@ -290,10 +290,10 @@ void GCLiveAnalysis::checkBasicSSA(PtrLiveData &Data) { | |||
| 290 | 290 | ||
| 291 | 291 | ||
| 292 | 292 | ||
| 293 | -// Conservatively identifies any definitions which might be live at the | 293 | +// Conservatively identifies any definitions which might be live across the |
| 294 | -// given instruction. The analysis is performed immediately before the | 294 | +// given parse point. For statepoint insertion we care about values that remain |
| 295 | -// given instruction. Values defined by that instruction are not considered | 295 | +// live *after* the current call finishes, not values used only as operands of |
| 296 | -// live. Values used by that instruction are considered live. | 296 | +// the current call itself. |
| 297 | void GCLiveAnalysis::analyzeParsePointLiveness(CallBase *Call, | 297 | void GCLiveAnalysis::analyzeParsePointLiveness(CallBase *Call, |
| 298 | SetVector<Value *> &LiveSet) { | 298 | SetVector<Value *> &LiveSet) { |
| 299 | findLiveSetAtInst(Call, LiveSet); | 299 | findLiveSetAtInst(Call, LiveSet); |
| @@ -437,8 +437,9 @@ void GCLiveAnalysis::computeLiveness() { | |||
| 437 | 437 | ||
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | -/// Given results from the dataflow liveness computation, find the set of live | 440 | +/// Given results from the dataflow liveness computation, find the set of values |
| 441 | -/// Values at a particular instruction. | 441 | +/// live immediately after the given instruction. The instruction result itself |
| 442 | +/// is never considered live at that point. | ||
| 442 | void GCLiveAnalysis::findLiveSetAtInst(Instruction *Inst, | 443 | void GCLiveAnalysis::findLiveSetAtInst(Instruction *Inst, |
| 443 | SetVector<Value *> &Out) { | 444 | SetVector<Value *> &Out) { |
| 444 | BasicBlock *BB = Inst->getParent(); | 445 | BasicBlock *BB = Inst->getParent(); |
| @@ -451,12 +452,32 @@ void GCLiveAnalysis::findLiveSetAtInst(Instruction *Inst, | |||
| 451 | auto BI = InstLiveSetCache.count(BB) | 452 | auto BI = InstLiveSetCache.count(BB) |
| 452 | ? InstLiveSetCache[BB].first->getIterator().getReverse() | 453 | ? InstLiveSetCache[BB].first->getIterator().getReverse() |
| 453 | : BB->rbegin(); | 454 | : BB->rbegin(); |
| 454 | - // We want to handle the statepoint itself oddly. It's | 455 | + // Liveness for a parse point is defined at the program point immediately |
| 455 | - // call result is not live (normal), nor are it's arguments | 456 | + // after the call. This trims values that are consumed only by the current |
| 456 | - // (unless they're used again later). This adjustment is | 457 | + // call and are dead afterwards. |
| 457 | - // specifically what we need to relocate | 458 | + computeLiveInValues(BI, Inst->getIterator().getReverse(), LiveOut); |
LGTM ![]() ![]() | |||
| 458 | - computeLiveInValues(BI, ++Inst->getIterator().getReverse(), LiveOut); | ||
| 459 | LiveOut.remove(Inst); | 459 | LiveOut.remove(Inst); |
所以这个地方 其实是不是可以删除的 ![]() ![]() | |||
| 460 | + // For FFI/runtime calls (callee does not have cangjie GC), the callee has | ||
| 461 | + // no cangjie safepoint and cannot relocate GC pointer arguments itself. | ||
| 462 | + // The caller must record these pointers in gc-live so the runtime updates | ||
| 463 | + // the caller's frame slot when GC moves the object during the call. | ||
| 464 | + // For cangjie-to-cangjie calls (callee has gc "cangjie"), the callee has | ||
| 465 | + // its own safepoints that handle relocation of its incoming arguments. | ||
| 466 | + // The caller can safely trim these call args, which keeps GCRelocates | ||
| 467 | + // empty and enables STATEPOINT_TAIL_CALL for such calls. | ||
| 468 | + if (auto *Call = dyn_cast<CallBase>(Inst)) { | ||
| 469 | + Function *Callee = Call->getCalledFunction(); | ||
| 470 | + bool CalleeHasCangjieGC = | ||
| 471 | + Callee && Callee->hasGC() && Callee->getGC() == "cangjie"; | ||
| 472 | + if (!CalleeHasCangjieGC) { | ||
| 473 | + for (Value *Arg : Call->args()) { | ||
| 474 | + if (isa<Constant>(Arg)) | ||
| 475 | + continue; | ||
| 476 | + if (isHandledGCPointerType(Arg->getType()) && !FakeGCPtrs.count(Arg)) | ||
| 477 | + LiveOut.insert(Arg); | ||
前面的 ++Inst->getIterator().getReverse() -> Inst->getIterator().getReverse() ,是因为之前的liveness 分析过于保守,而FFI 走到c ,是没有statepoint的, 所以必须要加入liveout 中, 是这样么 ![]() ![]() | |||
| 478 | + } | ||
| 479 | + } | ||
| 480 | + } | ||
| 460 | Out.insert(LiveOut.begin(), LiveOut.end()); | 481 | Out.insert(LiveOut.begin(), LiveOut.end()); |
| 461 | InstLiveSetCache[BB] = {Inst, Out}; | 482 | InstLiveSetCache[BB] = {Inst, Out}; |
| 462 | } | 483 | } |
| @@ -7,7 +7,7 @@ target triple = "aarch64-unknown-linux-gnu" | |||
| 7 | define void @test() "frame-pointer"="all" gc "statepoint-example" { | 7 | define void @test() "frame-pointer"="all" gc "statepoint-example" { |
| 8 | entry: | 8 | entry: |
| 9 | %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, void ()* elementtype(void ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live" ()] | 9 | %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, void ()* elementtype(void ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live" ()] |
| 10 | -; CHECK: STATEPOINT 0, 0, 0, @return_i1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, csr_aarch64_aapcs, implicit-def $sp, implicit-def dead early-clobber $lr | 10 | +; CHECK: STATEPOINT_TAIL_CALL 0, 0, 0, @return_i1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, csr_aarch64_aapcs, implicit-def dead early-clobber $lr |
| 11 | ret void | 11 | ret void |
| 12 | } | 12 | } |
| 13 | 13 | ||
| @@ -125,10 +125,9 @@ define void @test_void_vararg() gc "statepoint-example" { | |||
| 125 | ; CHECK-NEXT: .cfi_offset w30, -16 | 125 | ; CHECK-NEXT: .cfi_offset w30, -16 |
| 126 | ; CHECK-NEXT: mov w0, #42 | 126 | ; CHECK-NEXT: mov w0, #42 |
| 127 | ; CHECK-NEXT: mov w1, #43 | 127 | ; CHECK-NEXT: mov w1, #43 |
| 128 | -; CHECK-NEXT: bl varargf | ||
| 129 | -; CHECK-NEXT: .Ltmp6: | ||
| 130 | ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload | 128 | ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload |
| 131 | -; CHECK-NEXT: ret | 129 | +; CHECK-NEXT: b varargf |
| 130 | +; CHECK-NEXT: .Ltmp6: | ||
| 132 | ; Check a statepoint wrapping a *void* returning vararg function works | 131 | ; Check a statepoint wrapping a *void* returning vararg function works |
| 133 | entry: | 132 | entry: |
| 134 | %safepoint_token = tail call token (i64, i32, void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(i64 0, i32 0, void (i32, ...)* elementtype(void (i32, ...)) @varargf, i32 2, i32 0, i32 42, i32 43, i32 0, i32 0) | 133 | %safepoint_token = tail call token (i64, i32, void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(i64 0, i32 0, void (i32, ...)* elementtype(void (i32, ...)) @varargf, i32 2, i32 0, i32 42, i32 43, i32 0, i32 0) |
| @@ -8,23 +8,23 @@ | |||
| 8 | declare void @cj_stack_grow() | 8 | declare void @cj_stack_grow() |
| 9 | 9 | ||
| 10 | define internal void @test_vec_use_fp(%record* nocapture sret(%record) %0, i8 addrspace(1)* nocapture %1, %TypeInfo* nocapture %2, %string* %3, i64 %4, <2 x i64> %5, void (%Unit.Type*, i8 addrspace(1)*, %record*)* %6) #14 gc "cangjie" { | 10 | define internal void @test_vec_use_fp(%record* nocapture sret(%record) %0, i8 addrspace(1)* nocapture %1, %TypeInfo* nocapture %2, %string* %3, i64 %4, <2 x i64> %5, void (%Unit.Type*, i8 addrspace(1)*, %record*)* %6) #14 gc "cangjie" { |
| 11 | -; CHECK-LABEL: .Lstack.check.end0: | 11 | +; CHECK-LABEL: test_vec_use_fp: |
| 12 | -; CHECK-NEXT: movq %rdi, -40(%rbp) | 12 | +; CHECK: movq %rdi, -40(%rbp) |
| 13 | -; CHECK-NEXT: movdqu %xmm0, -24(%rbp) | 13 | +; CHECK: callq CJ_MCC_StackCheck@PLT |
| 14 | -; CHECK-NEXT: # %bb.1: | ||
| 15 | -; CHECK-NEXT: leaq -32(%rbp), %rax | ||
| 16 | -; CHECK-NEXT: movq %rax, -48(%rbp) | ||
| 17 | -; CHECK-NEXT: callq cj_stack_grow@PLT | ||
| 18 | ; CHECK-LABEL: .Ltmp1: | 14 | ; CHECK-LABEL: .Ltmp1: |
| 15 | +; CHECK: movdqu %xmm0, -24(%rbp) | ||
| 16 | +; CHECK: leaq -32(%rbp), %rax | ||
| 17 | +; CHECK: movq %rax, -48(%rbp) | ||
| 18 | +; CHECK: callq cj_stack_grow@PLT | ||
| 19 | ; CHECK-LABEL: .Ltmp2: | 19 | ; CHECK-LABEL: .Ltmp2: |
| 20 | -; CHECK: .long .Ltmp1-test_vec_use_fp | 20 | +; CHECK: .long .Ltmp1-test_vec_use_fp |
| 21 | ; CHECK-NEXT: #[RegIdx: -1, SlotIdx: -1, LNIdx: -1, DerivedStartIdx: -1, SPRegIdx: -1, SPSlotIdx: 0] | 21 | ; CHECK-NEXT: #[RegIdx: -1, SlotIdx: -1, LNIdx: -1, DerivedStartIdx: -1, SPRegIdx: -1, SPSlotIdx: 0] |
| 22 | ; CHECK: .long .Ltmp2-test_vec_use_fp | 22 | ; CHECK: .long .Ltmp2-test_vec_use_fp |
| 23 | -; CHECK-NEXT: #[RegIdx: -1, SlotIdx: -1, LNIdx: -1, DerivedStartIdx: -1, SPRegIdx: 0, SPSlotIdx: -1] | 23 | +; CHECK-NEXT: #[RegIdx: -1, SlotIdx: -1, LNIdx: -1, DerivedStartIdx: -1, SPRegIdx: -1, SPSlotIdx: 1] |
| 24 | -; CHECK: #RegNums: 1 | 24 | +; CHECK: #RegNums: 0 |
| 25 | -; CHECK: #Idx[0]: (0x236=566), rdx, rcx, rsi, rdi, r9 | 25 | +; CHECK: #SlotsNums: 2 |
| 26 | -; CHECK: #SlotsNums: 1 | 26 | +; CHECK: #Idx[0]: BaseOffset: -40, SlotBits: 0x1[ -40 ] |
| 27 | -; CHECK: #Idx[0]: BaseOffset: -40, SlotBits: 0x3[ -40 -48 ] | 27 | +; CHECK: #Idx[1]: BaseOffset: -40, SlotBits: 0x3[ -40 -48 ] |
| 28 | ; CHECK: #LineNumbersNums: 0 | 28 | ; CHECK: #LineNumbersNums: 0 |
| 29 | ; CHECK: #DerivedInfoNums: 0 | 29 | ; CHECK: #DerivedInfoNums: 0 |
| 30 | entry: | 30 | entry: |
| @@ -45,4 +45,4 @@ body: | |||
| 45 | ; Function Attrs: argmemonly nocallback nofree nounwind willreturn writeonly | 45 | ; Function Attrs: argmemonly nocallback nofree nounwind willreturn writeonly |
| 46 | declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #1 | 46 | declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #1 |
| 47 | declare void @CJ_MCC_StackCheck() | 47 | declare void @CJ_MCC_StackCheck() |
| 48 | -declare token @llvm.cj.gc.statepoint(...) | 48 | +declare token @llvm.cj.gc.statepoint(...) |
| @@ -0,0 +1,32 @@ | |||
| 1 | +; Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. | ||
| 2 | +; This source file is part of the Cangjie project, licensed under Apache-2.0 | ||
| 3 | +; with Runtime Library Exception. | ||
| 4 | + | ||
| 5 | +; See https://cangjie-lang.cn/pages/LICENSE for license information. | ||
| 6 | + | ||
| 7 | +; RUN: llc -O0 --cangjie-pipeline -mtriple x86_64-pc-linux-gnu < %s | FileCheck %s | ||
| 8 | + | ||
| 9 | +; Repeated callsites with the same derived/base location sequence should share | ||
| 10 | +; one compressed DerivedInfo entry instead of appending duplicate table rows. | ||
| 11 | + | ||
| 12 | +; CHECK: #StackMapItem nums:2 | ||
| 13 | +; CHECK: #[RegIdx: -1, SlotIdx: 0, LNIdx: -1, DerivedStartIdx: 0, SPRegIdx: -1, SPSlotIdx: -1] | ||
| 14 | +; CHECK: #[RegIdx: -1, SlotIdx: 0, LNIdx: -1, DerivedStartIdx: 0, SPRegIdx: -1, SPSlotIdx: -1] | ||
| 15 | +; CHECK: #DerivedInfoNums: 1 | ||
| 16 | +; CHECK-NEXT: {{.*}}#Idx[0]: RegIdx: -1, SlotIdx: 1 | ||
| 17 | + | ||
| 18 | +declare cangjiegccc void @g0() | ||
| 19 | +declare token @llvm.cj.gc.statepoint(...) | ||
| 20 | +declare i8 addrspace(1)* @llvm.cj.gc.relocate.p1i8(token, i32 immarg, | ||
| 21 | + i32 immarg) | ||
| 22 | + | ||
| 23 | +define i8 addrspace(1)* @dedup(i8 addrspace(1)* %base, | ||
| 24 | + i8 addrspace(1)* %derived) gc "cangjie" { | ||
| 25 | +entry: | ||
| 26 | + %t0 = call cangjiegccc token (...) @llvm.cj.gc.statepoint(i64 1, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %base, i8 addrspace(1)* %derived) ] | ||
| 27 | + %base0 = call coldcc i8 addrspace(1)* @llvm.cj.gc.relocate.p1i8(token %t0, i32 0, i32 0) | ||
| 28 | + %derived0 = call coldcc i8 addrspace(1)* @llvm.cj.gc.relocate.p1i8(token %t0, i32 0, i32 1) | ||
| 29 | + %t1 = call cangjiegccc token (...) @llvm.cj.gc.statepoint(i64 2, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %base0, i8 addrspace(1)* %derived0) ] | ||
| 30 | + %derived1 = call coldcc i8 addrspace(1)* @llvm.cj.gc.relocate.p1i8(token %t1, i32 0, i32 1) | ||
| 31 | + ret i8 addrspace(1)* %derived1 | ||
| 32 | +} | ||
| @@ -124,11 +124,10 @@ define void @test_void_vararg() gc "statepoint-example" { | |||
| 124 | ; CHECK-NEXT: .cfi_def_cfa_offset 16 | 124 | ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| 125 | ; CHECK-NEXT: movl $42, %edi | 125 | ; CHECK-NEXT: movl $42, %edi |
| 126 | ; CHECK-NEXT: movl $43, %esi | 126 | ; CHECK-NEXT: movl $43, %esi |
| 127 | -; CHECK-NEXT: callq varargf@PLT | 127 | +; CHECK-NEXT: addq $8, %rsp |
| 128 | -; CHECK-NEXT: .Ltmp6: | ||
| 129 | -; CHECK-NEXT: popq %rax | ||
| 130 | ; CHECK-NEXT: .cfi_def_cfa_offset 8 | 128 | ; CHECK-NEXT: .cfi_def_cfa_offset 8 |
| 131 | -; CHECK-NEXT: retq | 129 | +; CHECK-NEXT: jmp varargf@PLT # TAILCALL |
| 130 | +; CHECK-NEXT: .Ltmp6: | ||
| 132 | ; Check a statepoint wrapping a *ptr returning vararg function works | 131 | ; Check a statepoint wrapping a *ptr returning vararg function works |
| 133 | entry: | 132 | entry: |
| 134 | %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (i32, ...)) @varargf, i32 2, i32 0, i32 42, i32 43, i32 0, i32 0) | 133 | %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (i32, ...)) @varargf, i32 2, i32 0, i32 42, i32 43, i32 0, i32 0) |
| @@ -65,11 +65,10 @@ define void @test_deopt_use(ptr addrspace(1) %ptr) gc "statepoint-example" { | |||
| 65 | ; CHECK-NEXT: pushq %rax | 65 | ; CHECK-NEXT: pushq %rax |
| 66 | ; CHECK-NEXT: .cfi_def_cfa_offset 16 | 66 | ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| 67 | ; CHECK-NEXT: movq %rdi, (%rsp) | 67 | ; CHECK-NEXT: movq %rdi, (%rsp) |
| 68 | -; CHECK-NEXT: callq f@PLT | 68 | +; CHECK-NEXT: addq $8, %rsp |
| 69 | -; CHECK-NEXT: .Ltmp2: | ||
| 70 | -; CHECK-NEXT: popq %rax | ||
| 71 | ; CHECK-NEXT: .cfi_def_cfa_offset 8 | 69 | ; CHECK-NEXT: .cfi_def_cfa_offset 8 |
| 72 | -; CHECK-NEXT: retq | 70 | +; CHECK-NEXT: jmp f@PLT # TAILCALL |
| 71 | +; CHECK-NEXT: .Ltmp2: | ||
| 73 | tail call token (i64, i32, ptr, i32, i32, ...) | 72 | tail call token (i64, i32, ptr, i32, i32, ...) |
| 74 | @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @f, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %ptr), "deopt" (ptr addrspace(1) %ptr, i32 undef)] | 73 | @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @f, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %ptr), "deopt" (ptr addrspace(1) %ptr, i32 undef)] |
| 75 | ret void | 74 | ret void |
| @@ -81,11 +80,10 @@ define void @test_dse(ptr addrspace(1) %ptr) gc "statepoint-example" { | |||
| 81 | ; CHECK: # %bb.0: | 80 | ; CHECK: # %bb.0: |
| 82 | ; CHECK-NEXT: pushq %rax | 81 | ; CHECK-NEXT: pushq %rax |
| 83 | ; CHECK-NEXT: .cfi_def_cfa_offset 16 | 82 | ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| 84 | -; CHECK-NEXT: callq f@PLT | 83 | +; CHECK-NEXT: addq $8, %rsp |
| 85 | -; CHECK-NEXT: .Ltmp3: | ||
| 86 | -; CHECK-NEXT: popq %rax | ||
| 87 | ; CHECK-NEXT: .cfi_def_cfa_offset 8 | 84 | ; CHECK-NEXT: .cfi_def_cfa_offset 8 |
| 88 | -; CHECK-NEXT: retq | 85 | +; CHECK-NEXT: jmp f@PLT # TAILCALL |
| 86 | +; CHECK-NEXT: .Ltmp3: | ||
| 89 | tail call token (i64, i32, ptr, i32, i32, ...) | 87 | tail call token (i64, i32, ptr, i32, i32, ...) |
| 90 | @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @f, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %ptr)] | 88 | @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @f, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %ptr)] |
| 91 | ret void | 89 | ret void |
| @@ -68,7 +68,7 @@ declare void @"_ZN11std$FS$core18NoneValueException6<init>Ev"(i8 addrspace(1)*) | |||
| 68 | declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1) | 68 | declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1) |
| 69 | declare void @llvm.memset.p0i8.i64(i8*, i8, i64, i1) | 69 | declare void @llvm.memset.p0i8.i64(i8*, i8, i64, i1) |
| 70 | 70 | ||
| 71 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 4, i32 0, void ()* @CJ_MCC_StackCheck, i32 0, i32 0) | 71 | +; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 5, i32 0, void ()* @CJ_MCC_StackCheck, i32 0, i32 0) |
| 72 | 72 | ||
| 73 | define void @foo(%"record._ZN7default11std$FS$core5RangeItE"* noalias nocapture writeonly sret(%"record._ZN7default11std$FS$core5RangeItE") %0, i8 addrspace(1)* nocapture readnone %this) gc "cangjie" personality i32* null { | 73 | define void @foo(%"record._ZN7default11std$FS$core5RangeItE"* noalias nocapture writeonly sret(%"record._ZN7default11std$FS$core5RangeItE") %0, i8 addrspace(1)* nocapture readnone %this) gc "cangjie" personality i32* null { |
| 74 | entry: | 74 | entry: |
| @@ -9,7 +9,7 @@ entry: | |||
| 9 | %r = alloca %struct | 9 | %r = alloca %struct |
| 10 | br label %bb0 | 10 | br label %bb0 |
| 11 | 11 | ||
| 12 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @testcase, i32 0, i32 0) | 12 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @testcase, i32 0, i32 0) |
| 13 | ; | 13 | ; |
| 14 | bb0: | 14 | bb0: |
| 15 | call void @testcase() | 15 | call void @testcase() |
| @@ -21,7 +21,7 @@ bb1: | |||
| 21 | %2 = getelementptr inbounds %struct, %struct addrspace(1)* %1, i64 0, i32 0 ; CastInst and GEP are not a meaningful use point. | 21 | %2 = getelementptr inbounds %struct, %struct addrspace(1)* %1, i64 0, i32 0 ; CastInst and GEP are not a meaningful use point. |
| 22 | br label %bb2 | 22 | br label %bb2 |
| 23 | 23 | ||
| 24 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @testcase2, i32 1, i32 0, i8 addrspace(1)* %3) [ "gc-live"(i8 addrspace(1)* %3) ] | 24 | +; CHECK: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @testcase2, i32 1, i32 0, i8 addrspace(1)* %3) |
| 25 | ; | 25 | ; |
| 26 | bb2: | 26 | bb2: |
| 27 | call void @llvm.lifetime.start.p0i8(i64 8, i8* %0) | 27 | call void @llvm.lifetime.start.p0i8(i64 8, i8* %0) |
| @@ -14,7 +14,7 @@ entry: | |||
| 14 | br i1 %cond, label %for, label %end | 14 | br i1 %cond, label %for, label %end |
| 15 | 15 | ||
| 16 | ; CHECK: for: | 16 | ; CHECK: for: |
| 17 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record addrspace(1)* %.0, i8 addrspace(1)* %.03) [ "gc-live"(%record addrspace(1)* %.0, i8 addrspace(1)* %.03, %record %arg0), "struct-live"(%record* %0) ] | 17 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record addrspace(1)* %.0, i8 addrspace(1)* %.03) [ "gc-live"(%record addrspace(1)* %.0, i8 addrspace(1)* %.03, %record %arg0), "struct-live"(%record* %0) ] |
| 18 | ; | 18 | ; |
| 19 | for: ; preds = %entry, %for | 19 | for: ; preds = %entry, %for |
| 20 | %phi_i = phi i32 [ 0, %entry ], [ %i, %for ] | 20 | %phi_i = phi i32 [ 0, %entry ], [ %i, %for ] |
| @@ -26,7 +26,7 @@ for: ; preds = %entry, %for | |||
| 26 | br i1 %loop.cond, label %for, label %end | 26 | br i1 %loop.cond, label %for, label %end |
| 27 | 27 | ||
| 28 | ; CHECK: end: | 28 | ; CHECK: end: |
| 29 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record)* @g1, i32 1, i32 0, %record %arg0) [ "gc-live"(i8 addrspace(1)* %load, %record %arg0) ] | 29 | +; CHECK: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record)* @g1, i32 1, i32 0, %record %arg0) [ "gc-live"(i8 addrspace(1)* %load) ] |
| 30 | ; | 30 | ; |
| 31 | end: ; preds = %entry, %for | 31 | end: ; preds = %entry, %for |
| 32 | %phi_end = phi i8 addrspace(1)** [ %1, %entry], [ %phi, %for ] | 32 | %phi_end = phi i8 addrspace(1)** [ %1, %entry], [ %phi, %for ] |
| @@ -19,8 +19,8 @@ entry: | |||
| 19 | br label %body1 | 19 | br label %body1 |
| 20 | 20 | ||
| 21 | ; CHECK: body1: | 21 | ; CHECK: body1: |
| 22 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*)* @g0, i32 2, i32 0, i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1) [ "gc-live"(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1, %record %arg2), "struct-live"(%record* %1) ] | 22 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*)* @g0, i32 2, i32 0, i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1) [ "gc-live"(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1, %record %arg2), "struct-live"(%record* %1) ] |
| 23 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 (%record, i64)* @g1, i32 2, i32 0, %record %arg2, i64 0) [ "gc-live"(i8 addrspace(1)* %arg0.reloc, %record addrspace(1)* %arg1.reloc.casted, %record %arg2), "struct-live"(%record* %1) ] | 23 | +; CHECK: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 (%record, i64)* @g1, i32 2, i32 0, %record %arg2, i64 0) [ "gc-live"(i8 addrspace(1)* %arg0.reloc, %record addrspace(1)* %arg1.reloc.casted, %record %arg2), "struct-live"(%record* %1) ] |
| 24 | ; | 24 | ; |
| 25 | body1: ; preds = %entry | 25 | body1: ; preds = %entry |
| 26 | %sub = sub i64 %index, 1 | 26 | %sub = sub i64 %index, 1 |
| @@ -41,7 +41,7 @@ body2: ; preds = %ifthen2, %body1 | |||
| 41 | br i1 %icmpsge, label %ifthen1, label %ifelse1 | 41 | br i1 %icmpsge, label %ifthen1, label %ifelse1 |
| 42 | 42 | ||
| 43 | ; CHECK: ifthen1: | 43 | ; CHECK: ifthen1: |
| 44 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 (%record, i64)* @g1, i32 2, i32 0, %record %arg2, i64 %9) [ "gc-live"(i8 addrspace(1)* %.0, %record addrspace(1)* %.017, %record %arg2), "struct-live"(%record* %1) ] | 44 | +; CHECK: %token6 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 (%record, i64)* @g1, i32 2, i32 0, %record %arg2, i64 %9) [ "gc-live"(i8 addrspace(1)* %.0, %record addrspace(1)* %.015, %record %arg2), "struct-live"(%record* %1) ] |
| 45 | ; | 45 | ; |
| 46 | ifthen1: ; preds = %body2 | 46 | ifthen1: ; preds = %body2 |
| 47 | %10 = load i64, i64* %4 | 47 | %10 = load i64, i64* %4 |
| @@ -75,7 +75,7 @@ ifthen2: ; preds = %tmpend1 | |||
| 75 | br label %body2 | 75 | br label %body2 |
| 76 | 76 | ||
| 77 | ; CHECK: ifelse2: | 77 | ; CHECK: ifelse2: |
| 78 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i64)* @g2, i32 2, i32 0, i8 addrspace(1)* %arg0.reloc7, i64 %16) [ "gc-live"(i8 addrspace(1)* %arg0.reloc7, %record addrspace(1)* %arg1.reloc8.casted), "struct-live"(%record* %1) ] | 78 | +; CHECK: %token10 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i64)* @g2, i32 2, i32 0, i8 addrspace(1)* %arg0.reloc7, i64 %16) [ "gc-live"(i8 addrspace(1)* %arg0.reloc7, %record addrspace(1)* %arg1.reloc8.casted), "struct-live"(%record* %1) ] |
| 79 | ; | 79 | ; |
| 80 | ifelse2: ; preds = %tmpend1 | 80 | ifelse2: ; preds = %tmpend1 |
| 81 | %17 = load i64, i64* %4 | 81 | %17 = load i64, i64* %4 |
| @@ -107,7 +107,7 @@ tmpend2: ; preds = %tmp3, %tmp4 | |||
| 107 | br i1 %conv8, label %ifthen3, label %ifelse3 | 107 | br i1 %conv8, label %ifthen3, label %ifelse3 |
| 108 | 108 | ||
| 109 | ; CHECK: ifthen3: | 109 | ; CHECK: ifthen3: |
| 110 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*)* @g0, i32 2, i32 0, i8 addrspace(1)* %.1, %record addrspace(1)* %.118) [ "gc-live"(i8 addrspace(1)* %.1, %record addrspace(1)* %.118) ] | 110 | +; CHECK: %token14 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*)* @g0, i32 2, i32 0, i8 addrspace(1)* %.1, %record addrspace(1)* %.116) |
| 111 | ; | 111 | ; |
| 112 | ifthen3: ; preds = %tmpend2 | 112 | ifthen3: ; preds = %tmpend2 |
| 113 | call void @g0(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1) | 113 | call void @g0(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1) |
| @@ -63,7 +63,7 @@ start1: ; preds = %entry | |||
| 63 | br label %body1 | 63 | br label %body1 |
| 64 | 64 | ||
| 65 | ; CHECK: body1: | 65 | ; CHECK: body1: |
| 66 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record2 addrspace(1)* %arg1, i8 addrspace(1)* %arg0) [ "gc-live"(%record2 addrspace(1)* %arg5, i8 addrspace(1)* %arg0, i8 addrspace(1)* %arg4, i8 addrspace(1)* %arg2, %record2 addrspace(1)* %arg1, %record2 addrspace(1)* %arg3) ] | 66 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record2 addrspace(1)* %arg1, i8 addrspace(1)* %arg0) [ "gc-live"(%record2 addrspace(1)* %arg5, i8 addrspace(1)* %arg0, i8 addrspace(1)* %arg4, i8 addrspace(1)* %arg2, %record2 addrspace(1)* %arg1, %record2 addrspace(1)* %arg3) ] |
| 67 | ; | 67 | ; |
| 68 | body1: ; preds = %start1 | 68 | body1: ; preds = %start1 |
| 69 | %34 = call i64 @g0(%record2 addrspace(1)* %arg1, i8 addrspace(1)* %arg0) | 69 | %34 = call i64 @g0(%record2 addrspace(1)* %arg1, i8 addrspace(1)* %arg0) |
| @@ -74,7 +74,7 @@ tmp2: ; preds = %body1 | |||
| 74 | br label %tmpend1 | 74 | br label %tmpend1 |
| 75 | 75 | ||
| 76 | ; CHECK: tmp1: | 76 | ; CHECK: tmp1: |
| 77 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record2 addrspace(1)* %arg3.reloc.casted, i8 addrspace(1)* %arg2.reloc) [ "gc-live"(%record2 addrspace(1)* %arg5.reloc.casted, i8 addrspace(1)* %arg0.reloc, i8 addrspace(1)* %arg4.reloc, i8 addrspace(1)* %arg2.reloc, %record2 addrspace(1)* %arg1.reloc.casted, %record2 addrspace(1)* %arg3.reloc.casted) ] | 77 | +; CHECK: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record2 addrspace(1)* %arg3.reloc.casted, i8 addrspace(1)* %arg2.reloc) [ "gc-live"(%record2 addrspace(1)* %arg5.reloc.casted, i8 addrspace(1)* %arg0.reloc, i8 addrspace(1)* %arg4.reloc, i8 addrspace(1)* %arg2.reloc, %record2 addrspace(1)* %arg1.reloc.casted, %record2 addrspace(1)* %arg3.reloc.casted) ] |
| 78 | ; | 78 | ; |
| 79 | tmp1: ; preds = %body1 | 79 | tmp1: ; preds = %body1 |
| 80 | %35 = call i64 @g0(%record2 addrspace(1)* %arg3, i8 addrspace(1)* %arg2) | 80 | %35 = call i64 @g0(%record2 addrspace(1)* %arg3, i8 addrspace(1)* %arg2) |
| @@ -95,8 +95,8 @@ ifelse1: ; preds = %tmpend1 | |||
| 95 | br label %ifend1 | 95 | br label %ifend1 |
| 96 | 96 | ||
| 97 | ; CHECK: ifend1: | 97 | ; CHECK: ifend1: |
| 98 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i8 addrspace(1)*)* @g1, i32 1, i32 0, i8 addrspace(1)* %42) [ "gc-live"(i8 addrspace(1)* %.059, i8 addrspace(1)* %.060, i8 addrspace(1)* %.061, %record2 addrspace(1)* %.0, %record2 addrspace(1)* %.062, i8 addrspace(1)* %42), "struct-live"(i8 addrspace(1)** %25) ] | 98 | +; CHECK: %token10 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i8 addrspace(1)*)* @g1, i32 1, i32 0, i8 addrspace(1)* %42) [ "gc-live"(i8 addrspace(1)* %.055, i8 addrspace(1)* %.056, i8 addrspace(1)* %.057, %record2 addrspace(1)* %.0, %record2 addrspace(1)* %.058), "struct-live"(i8 addrspace(1)** %25) ] |
| 99 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i8 addrspace(1)*)* @g1, i32 1, i32 0, i8 addrspace(1)* %45) [ "gc-live"(i8 addrspace(1)* %arg0.reloc11, i8 addrspace(1)* %arg4.reloc12, i8 addrspace(1)* %arg2.reloc13, %record2 addrspace(1)* %arg5.reloc14.casted, %record2 addrspace(1)* %arg1.reloc15.casted, i8 addrspace(1)* %45), "struct-live"(i8 addrspace(1)** %25) ] | 99 | +; CHECK: %token17 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i8 addrspace(1)*)* @g1, i32 1, i32 0, i8 addrspace(1)* %44) [ "gc-live"(i8 addrspace(1)* %arg0.reloc11, i8 addrspace(1)* %arg4.reloc12, i8 addrspace(1)* %arg2.reloc13, %record2 addrspace(1)* %arg5.reloc14.casted, %record2 addrspace(1)* %arg1.reloc15.casted), "struct-live"(i8 addrspace(1)** %25) ] |
| 100 | ; | 100 | ; |
| 101 | ifend1: ; preds = %ifelse1 | 101 | ifend1: ; preds = %ifelse1 |
| 102 | %38 = getelementptr inbounds %record2, %record2 addrspace(1)* %arg3, i32 0, i32 0 | 102 | %38 = getelementptr inbounds %record2, %record2 addrspace(1)* %arg3, i32 0, i32 0 |
| @@ -116,10 +116,10 @@ ifend1: ; preds = %ifelse1 | |||
| 116 | br i1 %icmpeq2, label %ifthen2, label %ifelse2 | 116 | br i1 %icmpeq2, label %ifthen2, label %ifelse2 |
| 117 | 117 | ||
| 118 | ; CHECK: ifthen2: | 118 | ; CHECK: ifthen2: |
| 119 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g2, i32 2, i32 0, %record2 addrspace(1)* %arg1.reloc22.casted, i8 addrspace(1)* %arg0.reloc18) [ "gc-live"(i8 addrspace(1)* %arg0.reloc18, i8 addrspace(1)* %arg4.reloc19, i8 addrspace(1)* %arg2.reloc20, %record2 addrspace(1)* %arg5.reloc21.casted, %record2 addrspace(1)* %arg1.reloc22.casted), "struct-live"(i8 addrspace(1)** %25) ] | 119 | +; CHECK: %token24 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g2, i32 2, i32 0, %record2 addrspace(1)* %arg1.reloc22.casted, i8 addrspace(1)* %arg0.reloc18) [ "gc-live"(i8 addrspace(1)* %arg0.reloc18, i8 addrspace(1)* %arg4.reloc19, i8 addrspace(1)* %arg2.reloc20, %record2 addrspace(1)* %arg5.reloc21.casted, %record2 addrspace(1)* %arg1.reloc22.casted), "struct-live"(i8 addrspace(1)** %25) ] |
| 120 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record2 addrspace(1)* %arg1.reloc29.casted, i8 addrspace(1)* %arg0.reloc25) [ "gc-live"(i8 addrspace(1)* %arg0.reloc25, i8 addrspace(1)* %arg4.reloc26, i8 addrspace(1)* %arg2.reloc27, %record2 addrspace(1)* %arg5.reloc28.casted, %record2 addrspace(1)* %arg1.reloc29.casted), "struct-live"(i8 addrspace(1)** %25) ] | 120 | +; CHECK: %token31 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record2 addrspace(1)* %arg1.reloc29.casted, i8 addrspace(1)* %arg0.reloc25) [ "gc-live"(i8 addrspace(1)* %arg0.reloc25, i8 addrspace(1)* %arg4.reloc26, i8 addrspace(1)* %arg2.reloc27, %record2 addrspace(1)* %arg5.reloc28.casted, %record2 addrspace(1)* %arg1.reloc29.casted), "struct-live"(i8 addrspace(1)** %25) ] |
| 121 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g2, i32 2, i32 0, %record2 addrspace(1)* %arg1.reloc36.casted, i8 addrspace(1)* %arg0.reloc32) [ "gc-live"(i8 addrspace(1)* %arg0.reloc32, i8 addrspace(1)* %arg4.reloc33, i8 addrspace(1)* %arg2.reloc34, %record2 addrspace(1)* %arg5.reloc35.casted, %record2 addrspace(1)* %arg1.reloc36.casted), "struct-live"(i8 addrspace(1)** %25) ] | 121 | +; CHECK: %token38 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g2, i32 2, i32 0, %record2 addrspace(1)* %arg1.reloc36.casted, i8 addrspace(1)* %arg0.reloc32) [ "gc-live"(i8 addrspace(1)* %arg0.reloc32, i8 addrspace(1)* %arg4.reloc33, i8 addrspace(1)* %arg2.reloc34, %record2 addrspace(1)* %arg5.reloc35.casted), "struct-live"(i8 addrspace(1)** %25) ] |
| 122 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g2, i32 2, i32 0, %record2 addrspace(1)* %arg5.reloc42.casted, i8 addrspace(1)* %arg4.reloc40) [ "gc-live"(i8 addrspace(1)* %arg0.reloc39, i8 addrspace(1)* %arg4.reloc40, i8 addrspace(1)* %arg2.reloc41, %record2 addrspace(1)* %arg5.reloc42.casted), "struct-live"(i8 addrspace(1)** %25) ] | 122 | +; CHECK: %token44 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record2 addrspace(1)*, i8 addrspace(1)*)* @g2, i32 2, i32 0, %record2 addrspace(1)* %arg5.reloc42.casted, i8 addrspace(1)* %arg4.reloc40) [ "gc-live"(i8 addrspace(1)* %arg0.reloc39, i8 addrspace(1)* %arg4.reloc40, i8 addrspace(1)* %arg2.reloc41), "struct-live"(i8 addrspace(1)** %25) ] |
| 123 | ; | 123 | ; |
| 124 | ifthen2: ; preds = %ifend1 | 124 | ifthen2: ; preds = %ifend1 |
| 125 | %47 = call i64 @g2(%record2 addrspace(1)* %arg1, i8 addrspace(1)* %arg0) | 125 | %47 = call i64 @g2(%record2 addrspace(1)* %arg1, i8 addrspace(1)* %arg0) |
| @@ -142,8 +142,8 @@ ifthen2: ; preds = %ifend1 | |||
| 142 | br i1 %icmpsge1, label %tmp3, label %tmp4 | 142 | br i1 %icmpsge1, label %tmp3, label %tmp4 |
| 143 | 143 | ||
| 144 | ; CHECK: tmp4: | 144 | ; CHECK: tmp4: |
| 145 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %arg0.reloc46) [ "gc-live"(i8 addrspace(1)* %arg2.reloc48, i8 addrspace(1)* %arg0.reloc46) ] | 145 | +; CHECK: %token49 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %arg0.reloc45) [ "gc-live"(i8 addrspace(1)* %arg2.reloc47) ] |
| 146 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g4, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc52) [ "gc-live"(i8 addrspace(1)* %arg2.reloc52) ] | 146 | +; CHECK: %token52 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g4, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc50) |
| 147 | ; | 147 | ; |
| 148 | tmp4: ; preds = %ifthen2 | 148 | tmp4: ; preds = %ifthen2 |
| 149 | call void @g3(i8 addrspace(1)* %arg0) | 149 | call void @g3(i8 addrspace(1)* %arg0) |
| @@ -151,7 +151,7 @@ tmp4: ; preds = %ifthen2 | |||
| 151 | ret void | 151 | ret void |
| 152 | 152 | ||
| 153 | ; CHECK: tmp3: | 153 | ; CHECK: tmp3: |
| 154 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i64, i64, i64)* @g5, i32 5, i32 0, i8 addrspace(1)* %60, i8 addrspace(1)* %61, i64 0, i64 %62, i64 %63) [ "gc-live"(i8 addrspace(1)* %60, i8 addrspace(1)* %61) ] | 154 | +; CHECK: %token54 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i64, i64, i64)* @g5, i32 5, i32 0, i8 addrspace(1)* %58, i8 addrspace(1)* %59, i64 0, i64 %60, i64 %61) |
| 155 | ; | 155 | ; |
| 156 | tmp3: ; preds = %ifthen2 | 156 | tmp3: ; preds = %ifthen2 |
| 157 | %55 = add i64 %54, 1 | 157 | %55 = add i64 %54, 1 |
| @@ -61,7 +61,7 @@ entry: | |||
| 61 | br label %body1 | 61 | br label %body1 |
| 62 | 62 | ||
| 63 | ; CHECK: body1: | 63 | ; CHECK: body1: |
| 64 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i1 (i8 addrspace(1)*)* @g9, i32 1, i32 0, i8 addrspace(1)* %arg2) [ "gc-live"(i8 addrspace(1)* %arg0, i8 addrspace(1)* %arg2, %record addrspace(1)* %arg1), "struct-live"(%record* %2, %record* %4, %record* %18) ] | 64 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i1 (i8 addrspace(1)*)* @g9, i32 1, i32 0, i8 addrspace(1)* %arg2) [ "gc-live"(i8 addrspace(1)* %arg0, i8 addrspace(1)* %arg2, %record addrspace(1)* %arg1), "struct-live"(%record* %2, %record* %4, %record* %18) ] |
| 65 | ; | 65 | ; |
| 66 | body1: ; preds = %entry | 66 | body1: ; preds = %entry |
| 67 | %28 = call i1 @g9(i8 addrspace(1)* %arg2) | 67 | %28 = call i1 @g9(i8 addrspace(1)* %arg2) |
| @@ -76,7 +76,7 @@ ifelse1: ; preds = %body1 | |||
| 76 | br label %ifend1 | 76 | br label %ifend1 |
| 77 | 77 | ||
| 78 | ; CHECK: ifend1: | 78 | ; CHECK: ifend1: |
| 79 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record addrspace(1)*, i8 addrspace(1)*)* @g1, i32 2, i32 0, %record addrspace(1)* %arg1.reloc.casted, i8 addrspace(1)* %arg0.reloc) [ "gc-live"(i8 addrspace(1)* %arg2.reloc, i8 addrspace(1)* %arg0.reloc, %record addrspace(1)* %arg1.reloc.casted), "struct-live"(%record* %2, %record* %4, %record* %18) ] | 79 | +; CHECK: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record addrspace(1)*, i8 addrspace(1)*)* @g1, i32 2, i32 0, %record addrspace(1)* %arg1.reloc.casted, i8 addrspace(1)* %arg0.reloc) [ "gc-live"(i8 addrspace(1)* %arg2.reloc, %record addrspace(1)* %arg1.reloc.casted, i8 addrspace(1)* %arg0.reloc), "struct-live"(%record* %2, %record* %4, %record* %18) ] |
| 80 | ; | 80 | ; |
| 81 | ifend1: ; preds = %ifelse1 | 81 | ifend1: ; preds = %ifelse1 |
| 82 | %30 = getelementptr inbounds %record, %record addrspace(1)* %arg1, i32 0, i32 1 | 82 | %30 = getelementptr inbounds %record, %record addrspace(1)* %arg1, i32 0, i32 1 |
| @@ -95,8 +95,8 @@ ifend1: ; preds = %ifelse1 | |||
| 95 | br i1 %icmpeq, label %ifthen2, label %ifelse2 | 95 | br i1 %icmpeq, label %ifthen2, label %ifelse2 |
| 96 | 96 | ||
| 97 | ; CHECK: ifthen2: | 97 | ; CHECK: ifthen2: |
| 98 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g2, i32 2, i32 0, %record addrspace(1)* %arg1.reloc5.casted, i8 addrspace(1)* %arg0.reloc4) [ "gc-live"(i8 addrspace(1)* %arg2.reloc3, i8 addrspace(1)* %arg0.reloc4, %record addrspace(1)* %arg1.reloc5.casted) ] | 98 | +; CHECK: %token7 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g2, i32 2, i32 0, %record addrspace(1)* %arg1.reloc4.casted, i8 addrspace(1)* %arg0.reloc5) [ "gc-live"(i8 addrspace(1)* %arg2.reloc3) ] |
| 99 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc8) [ "gc-live"(i8 addrspace(1)* %arg2.reloc8) ] | 99 | +; CHECK: %token10 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc8) |
| 100 | ; | 100 | ; |
| 101 | ifthen2: ; preds = %ifend1 | 101 | ifthen2: ; preds = %ifend1 |
| 102 | call void @g2(%record addrspace(1)* %arg1, i8 addrspace(1)* %arg0) | 102 | call void @g2(%record addrspace(1)* %arg1, i8 addrspace(1)* %arg0) |
| @@ -107,7 +107,7 @@ ifelse2: ; preds = %ifend1 | |||
| 107 | br label %ifend2 | 107 | br label %ifend2 |
| 108 | 108 | ||
| 109 | ; CHECK: ifend2: | 109 | ; CHECK: ifend2: |
| 110 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i1 (i8 addrspace(1)*)* @g9, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc3) [ "gc-live"(i8 addrspace(1)* %arg2.reloc3, i8 addrspace(1)* %arg0.reloc4, %record addrspace(1)* %arg1.reloc5.casted), "struct-live"(%record* %2, %record* %4, %record* %18) ] | 110 | +; CHECK: %token12 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i1 (i8 addrspace(1)*)* @g9, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc3) [ "gc-live"(i8 addrspace(1)* %arg2.reloc3, %record addrspace(1)* %arg1.reloc4.casted, i8 addrspace(1)* %arg0.reloc5), "struct-live"(%record* %2, %record* %4, %record* %18) ] |
| 111 | ; | 111 | ; |
| 112 | ifend2: ; preds = %ifelse2 | 112 | ifend2: ; preds = %ifelse2 |
| 113 | %36 = call i1 @g9(i8 addrspace(1)* %arg2) | 113 | %36 = call i1 @g9(i8 addrspace(1)* %arg2) |
| @@ -195,7 +195,7 @@ tmpend4: ; preds = %tmp8, %tmp7 | |||
| 195 | br i1 %conv11, label %ifthen6, label %ifelse6 | 195 | br i1 %conv11, label %ifthen6, label %ifelse6 |
| 196 | 196 | ||
| 197 | ; CHECK: ifthen6: | 197 | ; CHECK: ifthen6: |
| 198 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc16) [ "gc-live"(i8 addrspace(1)* %arg2.reloc16) ] | 198 | +; CHECK: %token17 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc13) |
| 199 | ; | 199 | ; |
| 200 | ifthen6: ; preds = %tmpend4 | 200 | ifthen6: ; preds = %tmpend4 |
| 201 | call void @g10(i8 addrspace(1)* %arg2) | 201 | call void @g10(i8 addrspace(1)* %arg2) |
| @@ -205,8 +205,8 @@ ifelse6: ; preds = %tmpend4 | |||
| 205 | br label %ifend6 | 205 | br label %ifend6 |
| 206 | 206 | ||
| 207 | ; CHECK: ifend6: | 207 | ; CHECK: ifend6: |
| 208 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (%record addrspace(1)*, i8 addrspace(1)*, i64, i64)* @g3, i32 4, i32 0, %record addrspace(1)* %arg1.reloc18.casted, i8 addrspace(1)* %arg0.reloc17, i64 %48, i64 %49) [ "gc-live"(i8 addrspace(1)* %arg2.reloc16, i8 addrspace(1)* %arg0.reloc17, %record addrspace(1)* %arg1.reloc18.casted), "struct-live"(%record* %18) ] | 208 | +; CHECK: %token19 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (%record addrspace(1)*, i8 addrspace(1)*, i64, i64)* @g3, i32 4, i32 0, %record addrspace(1)* %arg1.reloc14.casted, i8 addrspace(1)* %arg0.reloc15, i64 %48, i64 %49) [ "struct-live"(%record* %18) ] |
| 209 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i64)* @g4, i32 2, i32 0, i8 addrspace(1)* %50, i64 %sub) [ "gc-live"(i8 addrspace(1)* %50), "struct-live"(%record* %18) ] | 209 | +; CHECK: %token21 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i64)* @g4, i32 2, i32 0, i8 addrspace(1)* %50, i64 %sub) [ "struct-live"(%record* %18) ] |
| 210 | ; | 210 | ; |
| 211 | ifend6: ; preds = %ifelse6 | 211 | ifend6: ; preds = %ifelse6 |
| 212 | %48 = load i64, i64* %23 | 212 | %48 = load i64, i64* %23 |
| @@ -264,7 +264,7 @@ tmpend5: ; preds = %tmp10, %tmp9 | |||
| 264 | br i1 %conv21, label %ifthen9, label %ifelse9 | 264 | br i1 %conv21, label %ifthen9, label %ifelse9 |
| 265 | 265 | ||
| 266 | ; CHECK: ifthen9: | 266 | ; CHECK: ifthen9: |
| 267 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc16) [ "gc-live"(i8 addrspace(1)* %arg2.reloc16) ] | 267 | +; CHECK: %token23 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc13) |
| 268 | ; | 268 | ; |
| 269 | ifthen9: ; preds = %tmpend5 | 269 | ifthen9: ; preds = %tmpend5 |
| 270 | call void @g10(i8 addrspace(1)* %arg2) | 270 | call void @g10(i8 addrspace(1)* %arg2) |
| @@ -293,7 +293,7 @@ tmpend6: ; preds = %tmp11, %tmp12 | |||
| 293 | br i1 %conv29, label %tmp13, label %tmp14 | 293 | br i1 %conv29, label %tmp13, label %tmp14 |
| 294 | 294 | ||
| 295 | ; CHECK: tmp14: | 295 | ; CHECK: tmp14: |
| 296 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i64, i64)* @g8, i32 2, i32 0, i64 %sub23, i64 %64) [ "gc-live"(i8 addrspace(1)* %arg2.reloc16, i8 addrspace(1)* %arg0.reloc17, %record addrspace(1)* %arg1.reloc18.casted), "struct-live"(%record* %2, %record* %4) ] | 296 | +; CHECK: %token25 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i64, i64)* @g8, i32 2, i32 0, i64 %sub23, i64 %63) [ "gc-live"(i8 addrspace(1)* %arg2.reloc13, %record addrspace(1)* %arg1.reloc14.casted, i8 addrspace(1)* %arg0.reloc15), "struct-live"(%record* %2, %record* %4) ] |
| 297 | ; | 297 | ; |
| 298 | tmp14: ; preds = %tmpend6 | 298 | tmp14: ; preds = %tmpend6 |
| 299 | %64 = call i64 @g8(i64 %sub23, i64 %63) | 299 | %64 = call i64 @g8(i64 %sub23, i64 %63) |
| @@ -348,7 +348,7 @@ tmpend8: ; preds = %tmp16, %tmp15 | |||
| 348 | br i1 %conv40, label %ifthen11, label %ifelse11 | 348 | br i1 %conv40, label %ifthen11, label %ifelse11 |
| 349 | 349 | ||
| 350 | ; CHECK: ifthen11: | 350 | ; CHECK: ifthen11: |
| 351 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc16) [ "gc-live"(i8 addrspace(1)* %arg2.reloc16) ] | 351 | +; CHECK: %token30 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %arg2.reloc13) |
| 352 | ; | 352 | ; |
| 353 | ifthen11: ; preds = %tmpend8 | 353 | ifthen11: ; preds = %tmpend8 |
| 354 | call void @g10(i8 addrspace(1)* %arg2) | 354 | call void @g10(i8 addrspace(1)* %arg2) |
| @@ -378,7 +378,7 @@ tmpend9: ; preds = %tmp17, %tmp18 | |||
| 378 | br i1 %conv49, label %tmp19, label %tmp20 | 378 | br i1 %conv49, label %tmp19, label %tmp20 |
| 379 | 379 | ||
| 380 | ; CHECK: tmp20: | 380 | ; CHECK: tmp20: |
| 381 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i64, i64)* @g8, i32 2, i32 0, i64 %sub42, i64 %sub43) [ "gc-live"(i8 addrspace(1)* %arg2.reloc16, i8 addrspace(1)* %arg0.reloc17, %record addrspace(1)* %arg1.reloc18.casted), "struct-live"(%record* %2, %record* %4) ] | 381 | +; CHECK: %token32 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i64, i64)* @g8, i32 2, i32 0, i64 %sub42, i64 %sub43) [ "gc-live"(i8 addrspace(1)* %arg2.reloc13, %record addrspace(1)* %arg1.reloc14.casted, i8 addrspace(1)* %arg0.reloc15), "struct-live"(%record* %2, %record* %4) ] |
| 382 | ; | 382 | ; |
| 383 | tmp20: ; preds = %tmpend9 | 383 | tmp20: ; preds = %tmpend9 |
| 384 | %76 = call i64 @g8(i64 %sub42, i64 %sub43) | 384 | %76 = call i64 @g8(i64 %sub42, i64 %sub43) |
| @@ -416,15 +416,15 @@ ifend7: ; preds = %tmpend10, %tmpend7 | |||
| 416 | br i1 %icmpsge1, label %tmp21, label %tmp22 | 416 | br i1 %icmpsge1, label %tmp21, label %tmp22 |
| 417 | 417 | ||
| 418 | ; CHECK: tmp22: | 418 | ; CHECK: tmp22: |
| 419 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %.277) [ "gc-live"(i8 addrspace(1)* %.277) ] | 419 | +; CHECK: %token37 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %.265) |
| 420 | ; | 420 | ; |
| 421 | tmp22: ; preds = %ifend7 | 421 | tmp22: ; preds = %ifend7 |
| 422 | call void @g10(i8 addrspace(1)* %arg2) | 422 | call void @g10(i8 addrspace(1)* %arg2) |
| 423 | unreachable | 423 | unreachable |
| 424 | 424 | ||
| 425 | ; CHECK: tmp21: | 425 | ; CHECK: tmp21: |
| 426 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g5, i32 3, i32 0, %record addrspace(1)* %.280, i8 addrspace(1)* %.2, i64 %87) [ "gc-live"(i8 addrspace(1)* %.277, %record addrspace(1)* %.280, i8 addrspace(1)* %.2), "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %15) ] | 426 | +; CHECK: %token39 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g5, i32 3, i32 0, %record addrspace(1)* %.268, i8 addrspace(1)* %.2, i64 %86) [ "gc-live"(i8 addrspace(1)* %.265, %record addrspace(1)* %.268, i8 addrspace(1)* %.2), "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %15) ] |
| 427 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*, i64, i64)* @g6, i32 4, i32 0, %record addrspace(1)* %arg1.reloc51.casted, i8 addrspace(1)* %arg0.reloc52, i64 %87, i64 %88) [ "gc-live"(i8 addrspace(1)* %arg2.reloc50, %record addrspace(1)* %arg1.reloc51.casted, i8 addrspace(1)* %arg0.reloc52), "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %15) ] | 427 | +; CHECK: %token44 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*, i64, i64)* @g6, i32 4, i32 0, %record addrspace(1)* %arg1.reloc41.casted, i8 addrspace(1)* %arg0.reloc42, i64 %86, i64 %87) [ "gc-live"(i8 addrspace(1)* %arg2.reloc40, %record addrspace(1)* %arg1.reloc41.casted), "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %15) ] |
| 428 | ; | 428 | ; |
| 429 | tmp21: ; preds = %ifend7 | 429 | tmp21: ; preds = %ifend7 |
| 430 | %85 = bitcast i8 addrspace(1)* %arg2 to %array addrspace(1)* | 430 | %85 = bitcast i8 addrspace(1)* %arg2 to %array addrspace(1)* |
| @@ -475,7 +475,7 @@ ifend13: ; preds = %ifelse13, %ifthen13 | |||
| 475 | br i1 %icmpslt63, label %ifthen14, label %ifelse14 | 475 | br i1 %icmpslt63, label %ifthen14, label %ifelse14 |
| 476 | 476 | ||
| 477 | ; CHECK: ifthen14: | 477 | ; CHECK: ifthen14: |
| 478 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i8 addrspace(1)*, i64)* @g12, i32 2, i32 0, i8 addrspace(1)* %102, i64 %103) [ "gc-live"(i8 addrspace(1)* %.3, %record addrspace(1)* %.381, i8 addrspace(1)* %102), "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %15) ] | 478 | +; CHECK: %token48 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i64 (i8 addrspace(1)*, i64)* @g12, i32 2, i32 0, i8 addrspace(1)* %101, i64 %102) [ "gc-live"(i8 addrspace(1)* %.3, %record addrspace(1)* %.369), "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %15) ] |
| 479 | ; | 479 | ; |
| 480 | ifthen14: ; preds = %ifend13 | 480 | ifthen14: ; preds = %ifend13 |
| 481 | %100 = getelementptr inbounds %record, %record addrspace(1)* %arg1, i32 0, i32 0 | 481 | %100 = getelementptr inbounds %record, %record addrspace(1)* %arg1, i32 0, i32 0 |
| @@ -501,7 +501,7 @@ tmpend12: ; preds = %tmp24, %tmp23 | |||
| 501 | br i1 %conv69, label %ifthen15, label %ifelse15 | 501 | br i1 %conv69, label %ifthen15, label %ifelse15 |
| 502 | 502 | ||
| 503 | ; CHECK: ifthen15: | 503 | ; CHECK: ifthen15: |
| 504 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i64, i64, i64)* @g7, i32 5, i32 0, i8 addrspace(1)* %110, i8 addrspace(1)* %111, i64 %112, i64 %113, i64 %114) [ "gc-live"(i8 addrspace(1)* %arg2.reloc60, %record addrspace(1)* %arg1.reloc61.casted, i8 addrspace(1)* %110, i8 addrspace(1)* %111), "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %15) ] | 504 | +; CHECK: %token52 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i64, i64, i64)* @g7, i32 5, i32 0, i8 addrspace(1)* %108, i8 addrspace(1)* %109, i64 %110, i64 %111, i64 %112) [ "gc-live"(i8 addrspace(1)* %arg2.reloc49, %record addrspace(1)* %arg1.reloc50.casted), "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %15) ] |
| 505 | ; | 505 | ; |
| 506 | ifthen15: ; preds = %tmpend12 | 506 | ifthen15: ; preds = %tmpend12 |
| 507 | %107 = getelementptr inbounds %record, %record addrspace(1)* %arg1, i32 0, i32 0 | 507 | %107 = getelementptr inbounds %record, %record addrspace(1)* %arg1, i32 0, i32 0 |
| @@ -550,15 +550,15 @@ end1: ; preds = %ifelse12 | |||
| 550 | br i1 %icmpsge2, label %tmp25, label %tmp26 | 550 | br i1 %icmpsge2, label %tmp25, label %tmp26 |
| 551 | 551 | ||
| 552 | ; CHECK: tmp26: | 552 | ; CHECK: tmp26: |
| 553 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %.3) [ "gc-live"(i8 addrspace(1)* %.3) ] | 553 | +; CHECK: %token56 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* %.3) |
| 554 | ; | 554 | ; |
| 555 | tmp26: ; preds = %end1 | 555 | tmp26: ; preds = %end1 |
| 556 | call void @g10(i8 addrspace(1)* %arg2) | 556 | call void @g10(i8 addrspace(1)* %arg2) |
| 557 | unreachable | 557 | unreachable |
| 558 | 558 | ||
| 559 | ; CHECK: tmp25: | 559 | ; CHECK: tmp25: |
| 560 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i64, i64, i64)* @g7, i32 5, i32 0, i8 addrspace(1)* %125, i8 addrspace(1)* %126, i64 0, i64 0, i64 %127) [ "gc-live"(i8 addrspace(1)* %125, i8 addrspace(1)* %126), "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %5) ] | 560 | +; CHECK: %token58 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i64, i64, i64)* @g7, i32 5, i32 0, i8 addrspace(1)* %121, i8 addrspace(1)* %122, i64 0, i64 0, i64 %123) [ "struct-live"(%record* %2, %record* %4, i8 addrspace(1)** %5) ] |
| 561 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i64)* @g4, i32 2, i32 0, i8 addrspace(1)* %130, i64 %131) [ "gc-live"(i8 addrspace(1)* %130), "struct-live"(%record* %2, %record* %4) ] | 561 | +; CHECK: %token60 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i64)* @g4, i32 2, i32 0, i8 addrspace(1)* %124, i64 %125) [ "struct-live"(%record* %2, %record* %4) ] |
| 562 | ; | 562 | ; |
| 563 | tmp25: ; preds = %end1 | 563 | tmp25: ; preds = %end1 |
| 564 | %120 = bitcast i8 addrspace(1)* %arg2 to %array addrspace(1)* | 564 | %120 = bitcast i8 addrspace(1)* %arg2 to %array addrspace(1)* |
| @@ -578,7 +578,7 @@ tmp25: ; preds = %end1 | |||
| 578 | br i1 %icmpslt79, label %ifthen16, label %ifelse16 | 578 | br i1 %icmpslt79, label %ifthen16, label %ifelse16 |
| 579 | 579 | ||
| 580 | ; CHECK: ifthen16: | 580 | ; CHECK: ifthen16: |
| 581 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* null) [ "struct-live"(%record* %2) ] | 581 | +; CHECK: %token62 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g10, i32 1, i32 0, i8 addrspace(1)* null) [ "struct-live"(%record* %2) ] |
| 582 | ; | 582 | ; |
| 583 | ifthen16: ; preds = %tmp25 | 583 | ifthen16: ; preds = %tmp25 |
| 584 | %129 = addrspacecast %record* %3 to %record addrspace(1)* | 584 | %129 = addrspacecast %record* %3 to %record addrspace(1)* |
| @@ -23,7 +23,7 @@ declare { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %arg0, i64 %arg1) | |||
| 23 | define i64 @foo(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1, i64 %arg2, i8* %arg3) #0 gc "cangjie" { | 23 | define i64 @foo(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1, i64 %arg2, i8* %arg3) #0 gc "cangjie" { |
| 24 | ; CHECK-LABEL: foo | 24 | ; CHECK-LABEL: foo |
| 25 | ; CHECK: entry: | 25 | ; CHECK: entry: |
| 26 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %arg0) ] | 26 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %arg0) ] |
| 27 | ; | 27 | ; |
| 28 | entry: | 28 | entry: |
| 29 | %0 = alloca %record | 29 | %0 = alloca %record |
| @@ -85,9 +85,9 @@ ifelse3: ; preds = %ifthen1 | |||
| 85 | br label %body1 | 85 | br label %body1 |
| 86 | 86 | ||
| 87 | ; CHECK: ifthen3: | 87 | ; CHECK: ifthen3: |
| 88 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %20) ] | 88 | +; CHECK: %token39 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %20) ] |
| 89 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %38) [ "struct-live"(%record* %20) ] | 89 | +; CHECK: %token41 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %38) [ "struct-live"(%record* %20) ] |
| 90 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %39) [ "gc-live"(i8 addrspace(1)* %39) ] | 90 | +; CHECK: %token43 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %39) |
| 91 | ; | 91 | ; |
| 92 | ifthen3: ; preds = %ifthen1 | 92 | ifthen3: ; preds = %ifthen1 |
| 93 | call void @g1(i8* %arg3, i64 0, i64 0) | 93 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -107,14 +107,14 @@ body1: ; preds = %ifthen7, %ifelse3 | |||
| 107 | ] | 107 | ] |
| 108 | 108 | ||
| 109 | ; CHECK: ifthen5: | 109 | ; CHECK: ifthen5: |
| 110 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i64, i8*)* @g4, i32 2, i32 0, i64 0, i8* %arg3) [ "gc-live"(i8 addrspace(1)* %.0), "struct-live"(%record* %17, %record* %21) ] | 110 | +; CHECK: %token45 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i64, i8*)* @g4, i32 2, i32 0, i64 0, i8* %arg3) [ "gc-live"(i8 addrspace(1)* %.0), "struct-live"(%record* %17, %record* %21) ] |
| 111 | ; | 111 | ; |
| 112 | ifthen5: ; preds = %body1 | 112 | ifthen5: ; preds = %body1 |
| 113 | %44 = call i8 addrspace(1)* @g4(i64 0, i8* %arg3) | 113 | %44 = call i8 addrspace(1)* @g4(i64 0, i8* %arg3) |
| 114 | br label %body2 | 114 | br label %body2 |
| 115 | 115 | ||
| 116 | ; CHECK: ifthen7: | 116 | ; CHECK: ifthen7: |
| 117 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %.0, %array addrspace(1)* %.0190), "struct-live"(%record* %19, %record* %17, %record* %21, %record* %18) ] | 117 | +; CHECK: %token48 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %.0, %array addrspace(1)* %.0185), "struct-live"(%record* %19, %record* %17, %record* %21, %record* %18) ] |
| 118 | ; | 118 | ; |
| 119 | ifthen7: ; preds = %body1 | 119 | ifthen7: ; preds = %body1 |
| 120 | %45 = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %41, i64 1) | 120 | %45 = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %41, i64 1) |
| @@ -123,9 +123,9 @@ ifthen7: ; preds = %body1 | |||
| 123 | br i1 %conv2, label %ifthen8, label %body1 | 123 | br i1 %conv2, label %ifthen8, label %body1 |
| 124 | 124 | ||
| 125 | ; CHECK: ifthen8: | 125 | ; CHECK: ifthen8: |
| 126 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %19) ] | 126 | +; CHECK: %token51 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %19) ] |
| 127 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %49) [ "struct-live"(%record* %19) ] | 127 | +; CHECK: %token53 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %48) [ "struct-live"(%record* %19) ] |
| 128 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %50) [ "gc-live"(i8 addrspace(1)* %50) ] | 128 | +; CHECK: %token55 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %49) |
| 129 | ; | 129 | ; |
| 130 | ifthen8: ; preds = %ifthen7 | 130 | ifthen8: ; preds = %ifthen7 |
| 131 | call void @g1(i8* %arg3, i64 0, i64 0) | 131 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -148,9 +148,9 @@ ifelse9: ; preds = %ifthen6 | |||
| 148 | br i1 %conv5, label %ifthen10, label %ifelse10 | 148 | br i1 %conv5, label %ifthen10, label %ifelse10 |
| 149 | 149 | ||
| 150 | ; CHECK: ifthen9: | 150 | ; CHECK: ifthen9: |
| 151 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %18) ] | 151 | +; CHECK: %token57 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %18) ] |
| 152 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %55) [ "struct-live"(%record* %18) ] | 152 | +; CHECK: %token59 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %53) [ "struct-live"(%record* %18) ] |
| 153 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %56) [ "gc-live"(i8 addrspace(1)* %56) ] | 153 | +; CHECK: %token61 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %54) |
| 154 | ; | 154 | ; |
| 155 | ifthen9: ; preds = %ifthen6 | 155 | ifthen9: ; preds = %ifthen6 |
| 156 | call void @g1(i8* %arg3, i64 0, i64 0) | 156 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -164,9 +164,9 @@ ifelse10: ; preds = %ifelse9 | |||
| 164 | br i1 %icmpsgt1, label %tmp1, label %tmp2 | 164 | br i1 %icmpsgt1, label %tmp1, label %tmp2 |
| 165 | 165 | ||
| 166 | ; CHECK: ifthen10: | 166 | ; CHECK: ifthen10: |
| 167 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %17) ] | 167 | +; CHECK: %token63 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %17) ] |
| 168 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %58) [ "struct-live"(%record* %17) ] | 168 | +; CHECK: %token65 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %55) [ "struct-live"(%record* %17) ] |
| 169 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %59) [ "gc-live"(i8 addrspace(1)* %59) ] | 169 | +; CHECK: %token67 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %56) |
| 170 | ; | 170 | ; |
| 171 | ifthen10: ; preds = %ifelse9 | 171 | ifthen10: ; preds = %ifelse9 |
| 172 | call void @g1(i8* %arg3, i64 0, i64 0) | 172 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -176,9 +176,9 @@ ifthen10: ; preds = %ifelse9 | |||
| 176 | unreachable | 176 | unreachable |
| 177 | 177 | ||
| 178 | ; CHECK: tmp2: | 178 | ; CHECK: tmp2: |
| 179 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) | 179 | +; CHECK: %token69 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) |
| 180 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g6, i32 1, i32 0, i8 addrspace(1)* %61) [ "gc-live"(i8 addrspace(1)* %61) ] | 180 | +; CHECK: %token71 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g6, i32 1, i32 0, i8 addrspace(1)* %57) [ "gc-live"(i8 addrspace(1)* %57) ] |
| 181 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %62) [ "gc-live"(i8 addrspace(1)* %62) ] | 181 | +; CHECK: %token73 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %58) |
| 182 | ; | 182 | ; |
| 183 | tmp2: ; preds = %ifelse10 | 183 | tmp2: ; preds = %ifelse10 |
| 184 | %55 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) | 184 | %55 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) |
| @@ -187,8 +187,8 @@ tmp2: ; preds = %ifelse10 | |||
| 187 | unreachable | 187 | unreachable |
| 188 | 188 | ||
| 189 | ; CHECK: tmp1: | 189 | ; CHECK: tmp1: |
| 190 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i64, i8*)* @g4, i32 2, i32 0, i64 %conv4, i8* %arg3) [ "gc-live"(i8 addrspace(1)* %.0), "struct-live"(%record* %17, %record* %21) ] | 190 | +; CHECK: %token75 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i64, i8*)* @g4, i32 2, i32 0, i64 %conv4, i8* %arg3) [ "gc-live"(i8 addrspace(1)* %.0), "struct-live"(%record* %17, %record* %21) ] |
| 191 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 24) [ "gc-live"(i8 addrspace(1)* %arg0.reloc80, i8 addrspace(1)* %64), "struct-live"(%record* %17, %record* %21) ] | 191 | +; CHECK: %token78 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 24) [ "gc-live"(i8 addrspace(1)* %arg0.reloc76, i8 addrspace(1)* %59), "struct-live"(%record* %17, %record* %21) ] |
| 192 | ; | 192 | ; |
| 193 | tmp1: ; preds = %ifelse10 | 193 | tmp1: ; preds = %ifelse10 |
| 194 | %56 = call i8 addrspace(1)* @g4(i64 %conv4, i8* %arg3) | 194 | %56 = call i8 addrspace(1)* @g4(i64 %conv4, i8* %arg3) |
| @@ -202,7 +202,7 @@ tmp1: ; preds = %ifelse10 | |||
| 202 | ; CHECK: tmp4: | 202 | ; CHECK: tmp4: |
| 203 | ; CHECK-NEXT: [[REMAT0:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[TMP0:%.*]], i64 8 | 203 | ; CHECK-NEXT: [[REMAT0:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[TMP0:%.*]], i64 8 |
| 204 | ; CHECK-NEXT: [[REMAT1:%.*]] = bitcast i8 addrspace(1)* [[REMAT0]] to i8 addrspace(1)* addrspace(1)* | 204 | ; CHECK-NEXT: [[REMAT1:%.*]] = bitcast i8 addrspace(1)* [[REMAT0]] to i8 addrspace(1)* addrspace(1)* |
| 205 | -; CHECK-NEXT: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)*)* @g7, i32 3, i32 0, i8 addrspace(1)* %arg0.reloc83, i8 addrspace(1)* %65, i8 addrspace(1)* addrspace(1)* [[REMAT1]]) [ "gc-live"(i8 addrspace(1)* %arg0.reloc83, i8 addrspace(1)* %66, i8 addrspace(1)* %65), "struct-live"(%record* %17, %record* %21) ] | 205 | +; CHECK-NEXT: %token81 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)*)* @g7, i32 3, i32 0, i8 addrspace(1)* %arg0.reloc79, i8 addrspace(1)* %60, i8 addrspace(1)* addrspace(1)* %.remat35) [ "gc-live"(i8 addrspace(1)* %arg0.reloc79, i8 addrspace(1)* %61, i8 addrspace(1)* %60), "struct-live"(%record* %17, %record* %21) ] |
| 206 | ; | 206 | ; |
| 207 | tmp4: ; preds = %tmp1 | 207 | tmp4: ; preds = %tmp1 |
| 208 | call void @g7(i8 addrspace(1)* %arg0, i8 addrspace(1)* %57, i8 addrspace(1)* addrspace(1)* %59) | 208 | call void @g7(i8 addrspace(1)* %arg0, i8 addrspace(1)* %57, i8 addrspace(1)* addrspace(1)* %59) |
| @@ -220,7 +220,7 @@ tmpend2: ; preds = %tmp3, %tmp4 | |||
| 220 | ; CHECK: tmp6: | 220 | ; CHECK: tmp6: |
| 221 | ; CHECK-NEXT: [[REMAT2:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[TMP1:%.*]], i64 16 | 221 | ; CHECK-NEXT: [[REMAT2:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[TMP1:%.*]], i64 16 |
| 222 | ; CHECK-NEXT: [[REMAT3:%.*]] = bitcast i8 addrspace(1)* [[REMAT2]] to i64 addrspace(1)* | 222 | ; CHECK-NEXT: [[REMAT3:%.*]] = bitcast i8 addrspace(1)* [[REMAT2]] to i64 addrspace(1)* |
| 223 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i64, i8 addrspace(1)*, i64 addrspace(1)*)* @g8, i32 3, i32 0, i64 %arg2, i8 addrspace(1)* %.0196, i64 addrspace(1)* [[REMAT3]]) [ "gc-live"(i8 addrspace(1)* %.1, i8 addrspace(1)* %.0192, i8 addrspace(1)* %.0196), "struct-live"(%record* %17, %record* %21) ] | 223 | +; CHECK: %token84 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i64, i8 addrspace(1)*, i64 addrspace(1)*)* @g8, i32 3, i32 0, i64 %arg2, i8 addrspace(1)* %.0191, i64 addrspace(1)* %.remat29) [ "gc-live"(i8 addrspace(1)* %.1, i8 addrspace(1)* %.0187, i8 addrspace(1)* %.0191), "struct-live"(%record* %17, %record* %21) ] |
| 224 | ; | 224 | ; |
| 225 | tmp6: ; preds = %tmpend2 | 225 | tmp6: ; preds = %tmpend2 |
| 226 | call void @g8(i64 %arg2, i8 addrspace(1)* %57, i64 addrspace(1)* %62) | 226 | call void @g8(i64 %arg2, i8 addrspace(1)* %57, i64 addrspace(1)* %62) |
| @@ -231,7 +231,7 @@ tmp5: ; preds = %tmpend2 | |||
| 231 | br label %tmpend3 | 231 | br label %tmpend3 |
| 232 | 232 | ||
| 233 | ; CHECK: tmpend3: | 233 | ; CHECK: tmpend3: |
| 234 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 24) [ "gc-live"(i8 addrspace(1)* %.2, i8 addrspace(1)* %.1193, i8 addrspace(1)* %.1197), "struct-live"(%record* %17, %record* %21) ] | 234 | +; CHECK: %token87 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 24) [ "gc-live"(i8 addrspace(1)* %.2, i8 addrspace(1)* %.1188, i8 addrspace(1)* %.1192), "struct-live"(%record* %17, %record* %21) ] |
| 235 | ; | 235 | ; |
| 236 | tmpend3: ; preds = %tmp5, %tmp6 | 236 | tmpend3: ; preds = %tmp5, %tmp6 |
| 237 | %63 = call i8 addrspace(1)* @g5(i8* %arg3, i32 24) | 237 | %63 = call i8 addrspace(1)* @g5(i8* %arg3, i32 24) |
| @@ -243,7 +243,7 @@ tmpend3: ; preds = %tmp5, %tmp6 | |||
| 243 | br i1 %icmpsle2, label %tmp7, label %tmp8 | 243 | br i1 %icmpsle2, label %tmp7, label %tmp8 |
| 244 | 244 | ||
| 245 | ; CHECK: tmp8: | 245 | ; CHECK: tmp8: |
| 246 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)*)* @g7, i32 3, i32 0, i8 addrspace(1)* %79, i8 addrspace(1)* %76, i8 addrspace(1)* addrspace(1)* %81) [ "gc-live"(i8 addrspace(1)* %arg0.reloc92, i8 addrspace(1)* %77, i8 addrspace(1)* %76, i8 addrspace(1)* %78, i8 addrspace(1)* %79), "struct-live"(%record* %17, %record* %21) ] | 246 | +; CHECK: %token90 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)*)* @g7, i32 3, i32 0, i8 addrspace(1)* %74, i8 addrspace(1)* %71, i8 addrspace(1)* addrspace(1)* %76) [ "gc-live"(i8 addrspace(1)* %arg0.reloc88, i8 addrspace(1)* %72, i8 addrspace(1)* %71, i8 addrspace(1)* %73), "struct-live"(%record* %17, %record* %21) ] |
| 247 | ; | 247 | ; |
| 248 | tmp8: ; preds = %tmpend3 | 248 | tmp8: ; preds = %tmpend3 |
| 249 | call void @g7(i8 addrspace(1)* %64, i8 addrspace(1)* %63, i8 addrspace(1)* addrspace(1)* %66) | 249 | call void @g7(i8 addrspace(1)* %64, i8 addrspace(1)* %63, i8 addrspace(1)* addrspace(1)* %66) |
| @@ -260,7 +260,7 @@ tmpend4: ; preds = %tmp7, %tmp8 | |||
| 260 | br i1 %icmpsle2, label %tmp9, label %tmp10 | 260 | br i1 %icmpsle2, label %tmp9, label %tmp10 |
| 261 | 261 | ||
| 262 | ; CHECK: tmp10: | 262 | ; CHECK: tmp10: |
| 263 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i64, i8 addrspace(1)*, i64 addrspace(1)*)* @g8, i32 3, i32 0, i64 %87, i8 addrspace(1)* %.0199, i64 addrspace(1)* %89) [ "gc-live"(i8 addrspace(1)* %.3, i8 addrspace(1)* %.2194, i8 addrspace(1)* %.0199), "struct-live"(%record* %17, %record* %21) ] | 263 | +; CHECK: %token93 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i64, i8 addrspace(1)*, i64 addrspace(1)*)* @g8, i32 3, i32 0, i64 %81, i8 addrspace(1)* %.0194, i64 addrspace(1)* %83) [ "gc-live"(i8 addrspace(1)* %.3, i8 addrspace(1)* %.2189, i8 addrspace(1)* %.0194), "struct-live"(%record* %17, %record* %21) ] |
| 264 | ; | 264 | ; |
| 265 | tmp10: ; preds = %tmpend4 | 265 | tmp10: ; preds = %tmpend4 |
| 266 | call void @g8(i64 %68, i8 addrspace(1)* %63, i64 addrspace(1)* %70) | 266 | call void @g8(i64 %68, i8 addrspace(1)* %63, i64 addrspace(1)* %70) |
| @@ -271,7 +271,7 @@ tmp9: ; preds = %tmpend4 | |||
| 271 | br label %tmpend5 | 271 | br label %tmpend5 |
| 272 | 272 | ||
| 273 | ; CHECK: tmpend5: | 273 | ; CHECK: tmpend5: |
| 274 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, i64, i8 addrspace(1)*)* @g9, i32 3, i32 0, i8 addrspace(1)* %.3195, i64 %conv4, i8 addrspace(1)* %.1200) [ "gc-live"(i8 addrspace(1)* %.4, i8 addrspace(1)* %.3195, i8 addrspace(1)* %.1200), "struct-live"(%record* %17, %record* %21) ] | 274 | +; CHECK: %token96 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, i64, i8 addrspace(1)*)* @g9, i32 3, i32 0, i8 addrspace(1)* %.3190, i64 %conv4, i8 addrspace(1)* %.1195) [ "gc-live"(i8 addrspace(1)* %.4), "struct-live"(%record* %17, %record* %21) ] |
| 275 | ; | 275 | ; |
| 276 | tmpend5: ; preds = %tmp9, %tmp10 | 276 | tmpend5: ; preds = %tmp9, %tmp10 |
| 277 | %71 = call i8 addrspace(1)* @g9(i8 addrspace(1)* %56, i64 %conv4, i8 addrspace(1)* %63) | 277 | %71 = call i8 addrspace(1)* @g9(i8 addrspace(1)* %56, i64 %conv4, i8 addrspace(1)* %63) |
| @@ -305,9 +305,9 @@ tmp14: ; preds = %tmp12 | |||
| 305 | br label %tmpend7 | 305 | br label %tmpend7 |
| 306 | 306 | ||
| 307 | ; CHECK: tmp13: | 307 | ; CHECK: tmp13: |
| 308 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) [ "struct-live"(%record* %17) ] | 308 | +; CHECK: %token99 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) [ "struct-live"(%record* %17) ] |
| 309 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, %record addrspace(1)*)* @g10, i32 3, i32 0, i8 addrspace(1)* %111, i8 addrspace(1)* null, %record addrspace(1)* %112) [ "gc-live"(i8 addrspace(1)* %111), "struct-live"(%record* %17) ] | 309 | +; CHECK: %token101 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, %record addrspace(1)*)* @g10, i32 3, i32 0, i8 addrspace(1)* %103, i8 addrspace(1)* null, %record addrspace(1)* %104) [ "gc-live"(i8 addrspace(1)* %103), "struct-live"(%record* %17) ] |
| 310 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %113) [ "gc-live"(i8 addrspace(1)* %113) ] | 310 | +; CHECK: %token103 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %105) |
| 311 | ; | 311 | ; |
| 312 | tmp13: ; preds = %ifelse16, %tmp12 | 312 | tmp13: ; preds = %ifelse16, %tmp12 |
| 313 | %88 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) | 313 | %88 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) |
| @@ -339,9 +339,9 @@ ifelse11: ; preds = %tmp15 | |||
| 339 | br label %ifend11 | 339 | br label %ifend11 |
| 340 | 340 | ||
| 341 | ; CHECK: ifthen11: | 341 | ; CHECK: ifthen11: |
| 342 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %16) ] | 342 | +; CHECK: %token105 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %16) ] |
| 343 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %121) [ "struct-live"(%record* %16) ] | 343 | +; CHECK: %token107 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %112) [ "struct-live"(%record* %16) ] |
| 344 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %122) [ "gc-live"(i8 addrspace(1)* %122) ] | 344 | +; CHECK: %token109 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %113) |
| 345 | ; | 345 | ; |
| 346 | ifthen11: ; preds = %tmp15 | 346 | ifthen11: ; preds = %tmp15 |
| 347 | call void @g1(i8* %arg3, i64 0, i64 0) | 347 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -374,7 +374,7 @@ tmp20: ; preds = %tmp17 | |||
| 374 | br i1 %conv7, label %ifthen12, label %ifelse12 | 374 | br i1 %conv7, label %ifthen12, label %ifelse12 |
| 375 | 375 | ||
| 376 | ; CHECK: ifelse12: | 376 | ; CHECK: ifelse12: |
| 377 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(%array addrspace(1)* %.0204, i8 addrspace(1)* %.7, i8 addrspace(1)* %.1202), "struct-live"(%record* %14, %record* %21, %record* %13, %record* %12, %record* %17, %record* %15) ] | 377 | +; CHECK: %token111 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(%array addrspace(1)* %.0197, i8 addrspace(1)* %.7, i8 addrspace(1)* %.1199), "struct-live"(%record* %14, %record* %21, %record* %13, %record* %12, %record* %17, %record* %15) ] |
| 378 | ; | 378 | ; |
| 379 | ifelse12: ; preds = %tmp20 | 379 | ifelse12: ; preds = %tmp20 |
| 380 | %conv25 = extractvalue { i64, i1 } %105, 0 | 380 | %conv25 = extractvalue { i64, i1 } %105, 0 |
| @@ -384,9 +384,9 @@ ifelse12: ; preds = %tmp20 | |||
| 384 | br i1 %conv8, label %ifthen13, label %ifend11 | 384 | br i1 %conv8, label %ifthen13, label %ifend11 |
| 385 | 385 | ||
| 386 | ; CHECK: ifthen12: | 386 | ; CHECK: ifthen12: |
| 387 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %15) ] | 387 | +; CHECK: %token114 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %15) ] |
| 388 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %136) [ "struct-live"(%record* %15) ] | 388 | +; CHECK: %token116 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %126) [ "struct-live"(%record* %15) ] |
| 389 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %137) [ "gc-live"(i8 addrspace(1)* %137) ] | 389 | +; CHECK: %token118 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %127) |
| 390 | ; | 390 | ; |
| 391 | ifthen12: ; preds = %tmp20 | 391 | ifthen12: ; preds = %tmp20 |
| 392 | call void @g1(i8* %arg3, i64 0, i64 0) | 392 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -396,9 +396,9 @@ ifthen12: ; preds = %tmp20 | |||
| 396 | unreachable | 396 | unreachable |
| 397 | 397 | ||
| 398 | ; CHECK: ifthen13: | 398 | ; CHECK: ifthen13: |
| 399 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %14) ] | 399 | +; CHECK: %token120 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %14) ] |
| 400 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %139) [ "struct-live"(%record* %14) ] | 400 | +; CHECK: %token122 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %128) [ "struct-live"(%record* %14) ] |
| 401 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %140) [ "gc-live"(i8 addrspace(1)* %140) ] | 401 | +; CHECK: %token124 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %129) |
| 402 | ; | 402 | ; |
| 403 | ifthen13: ; preds = %ifelse12 | 403 | ifthen13: ; preds = %ifelse12 |
| 404 | call void @g1(i8* %arg3, i64 0, i64 0) | 404 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -419,9 +419,9 @@ ifelse14: ; preds = %tmp19 | |||
| 419 | br i1 %conv10, label %ifthen15, label %ifelse15 | 419 | br i1 %conv10, label %ifthen15, label %ifelse15 |
| 420 | 420 | ||
| 421 | ; CHECK: ifthen14: | 421 | ; CHECK: ifthen14: |
| 422 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %13) ] | 422 | +; CHECK: %token126 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %13) ] |
| 423 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %144) [ "struct-live"(%record* %13) ] | 423 | +; CHECK: %token128 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %132) [ "struct-live"(%record* %13) ] |
| 424 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %145) [ "gc-live"(i8 addrspace(1)* %145) ] | 424 | +; CHECK: %token130 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %133) |
| 425 | ; | 425 | ; |
| 426 | ifthen14: ; preds = %tmp19 | 426 | ifthen14: ; preds = %tmp19 |
| 427 | call void @g1(i8* %arg3, i64 0, i64 0) | 427 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -431,9 +431,9 @@ ifthen14: ; preds = %tmp19 | |||
| 431 | unreachable | 431 | unreachable |
| 432 | 432 | ||
| 433 | ; CHECK: ifthen15: | 433 | ; CHECK: ifthen15: |
| 434 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %12) ] | 434 | +; CHECK: %token132 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %12) ] |
| 435 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %147) [ "struct-live"(%record* %12) ] | 435 | +; CHECK: %token134 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %134) [ "struct-live"(%record* %12) ] |
| 436 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %148) [ "gc-live"(i8 addrspace(1)* %148) ] | 436 | +; CHECK: %token136 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %135) |
| 437 | ; | 437 | ; |
| 438 | ifthen15: ; preds = %ifelse14 | 438 | ifthen15: ; preds = %ifelse14 |
| 439 | call void @g1(i8* %arg3, i64 0, i64 0) | 439 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -454,7 +454,7 @@ tmp16: ; preds = %ifelse15, %tmp18, %tmpend7 | |||
| 454 | br i1 %conv11, label %ifthen16, label %ifelse16 | 454 | br i1 %conv11, label %ifthen16, label %ifelse16 |
| 455 | 455 | ||
| 456 | ; CHECK: ifelse16: | 456 | ; CHECK: ifelse16: |
| 457 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(%array addrspace(1)* %base_phi, %array addrspace(1)* %150, i8 addrspace(1)* %.8, i8 addrspace(1)* %.2203), "struct-live"(%record* %17, %record* %21) ] | 457 | +; CHECK: %token138 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(%array addrspace(1)* %base_phi, %array addrspace(1)* %136, i8 addrspace(1)* %.8, i8 addrspace(1)* %.2200), "struct-live"(%record* %17, %record* %21) ] |
| 458 | ; | 458 | ; |
| 459 | ifelse16: ; preds = %tmp16 | 459 | ifelse16: ; preds = %tmp16 |
| 460 | %conv17 = extractvalue { i64, i1 } %118, 0 | 460 | %conv17 = extractvalue { i64, i1 } %118, 0 |
| @@ -466,9 +466,9 @@ ifelse16: ; preds = %tmp16 | |||
| 466 | br i1 %icmpeq6, label %tmp13, label %tmpend7 | 466 | br i1 %icmpeq6, label %tmp13, label %tmpend7 |
| 467 | 467 | ||
| 468 | ; CHECK: ifthen16: | 468 | ; CHECK: ifthen16: |
| 469 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %21) ] | 469 | +; CHECK: %token141 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %21) ] |
| 470 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %158) [ "struct-live"(%record* %21) ] | 470 | +; CHECK: %token143 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %144) [ "struct-live"(%record* %21) ] |
| 471 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %159) [ "gc-live"(i8 addrspace(1)* %159) ] | 471 | +; CHECK: %token145 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %145) |
| 472 | ; | 472 | ; |
| 473 | ifthen16: ; preds = %tmp16 | 473 | ifthen16: ; preds = %tmp16 |
| 474 | call void @g1(i8* %arg3, i64 0, i64 0) | 474 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -487,9 +487,9 @@ tmp11: ; preds = %body3, %body2 | |||
| 487 | br i1 %icmpeq7, label %ifthen4, label %tmp38 | 487 | br i1 %icmpeq7, label %ifthen4, label %tmp38 |
| 488 | 488 | ||
| 489 | ; CHECK: ifthen4: | 489 | ; CHECK: ifthen4: |
| 490 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) [ "struct-live"(%record* %17) ] | 490 | +; CHECK: %token147 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) [ "struct-live"(%record* %17) ] |
| 491 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, %record addrspace(1)*)* @g10, i32 3, i32 0, i8 addrspace(1)* %162, i8 addrspace(1)* null, %record addrspace(1)* %163) [ "gc-live"(i8 addrspace(1)* %162), "struct-live"(%record* %17) ] | 491 | +; CHECK: %token149 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, %record addrspace(1)*)* @g10, i32 3, i32 0, i8 addrspace(1)* %147, i8 addrspace(1)* null, %record addrspace(1)* %148) [ "gc-live"(i8 addrspace(1)* %147), "struct-live"(%record* %17) ] |
| 492 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %164) [ "gc-live"(i8 addrspace(1)* %164) ] | 492 | +; CHECK: %token151 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %149) |
| 493 | ; | 493 | ; |
| 494 | ifthen4: ; preds = %tmp11 | 494 | ifthen4: ; preds = %tmp11 |
| 495 | %125 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) | 495 | %125 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) |
| @@ -530,9 +530,9 @@ ifelse17: ; preds = %ifthen2 | |||
| 530 | br i1 %icmpsgt3, label %tmp21, label %tmp22 | 530 | br i1 %icmpsgt3, label %tmp21, label %tmp22 |
| 531 | 531 | ||
| 532 | ; CHECK: ifthen17: | 532 | ; CHECK: ifthen17: |
| 533 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %11) ] | 533 | +; CHECK: %token153 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %11) ] |
| 534 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %177) [ "struct-live"(%record* %11) ] | 534 | +; CHECK: %token155 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %161) [ "struct-live"(%record* %11) ] |
| 535 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %178) [ "gc-live"(i8 addrspace(1)* %178) ] | 535 | +; CHECK: %token157 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %162) |
| 536 | ; | 536 | ; |
| 537 | ifthen17: ; preds = %ifthen2 | 537 | ifthen17: ; preds = %ifthen2 |
| 538 | call void @g1(i8* %arg3, i64 0, i64 0) | 538 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -602,9 +602,9 @@ tmp29: ; preds = %ifthen19, %tmp27 | |||
| 602 | br i1 %icmpeq11, label %tmp31, label %tmp32 | 602 | br i1 %icmpeq11, label %tmp31, label %tmp32 |
| 603 | 603 | ||
| 604 | ; CHECK: tmp31: | 604 | ; CHECK: tmp31: |
| 605 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) [ "struct-live"(%record* %17) ] | 605 | +; CHECK: %token159 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) [ "struct-live"(%record* %17) ] |
| 606 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, %record addrspace(1)*)* @g10, i32 3, i32 0, i8 addrspace(1)* %203, i8 addrspace(1)* null, %record addrspace(1)* %204) [ "gc-live"(i8 addrspace(1)* %203), "struct-live"(%record* %17) ] | 606 | +; CHECK: %token161 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, %record addrspace(1)*)* @g10, i32 3, i32 0, i8 addrspace(1)* %186, i8 addrspace(1)* null, %record addrspace(1)* %187) [ "gc-live"(i8 addrspace(1)* %186), "struct-live"(%record* %17) ] |
| 607 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %205) [ "gc-live"(i8 addrspace(1)* %205) ] | 607 | +; CHECK: %token163 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %188) |
| 608 | ; | 608 | ; |
| 609 | tmp31: ; preds = %ifelse22, %tmp29 | 609 | tmp31: ; preds = %ifelse22, %tmp29 |
| 610 | %163 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) | 610 | %163 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) |
| @@ -631,9 +631,9 @@ ifelse21: ; preds = %tmp33 | |||
| 631 | br i1 %icmpslt1, label %tmp34, label %body4 | 631 | br i1 %icmpslt1, label %tmp34, label %body4 |
| 632 | 632 | ||
| 633 | ; CHECK: ifthen21: | 633 | ; CHECK: ifthen21: |
| 634 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %5) ] | 634 | +; CHECK: %token165 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %5) ] |
| 635 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %211) [ "struct-live"(%record* %5) ] | 635 | +; CHECK: %token167 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %193) [ "struct-live"(%record* %5) ] |
| 636 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %212) [ "gc-live"(i8 addrspace(1)* %212) ] | 636 | +; CHECK: %token169 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %194) |
| 637 | ; | 637 | ; |
| 638 | ifthen21: ; preds = %tmp33 | 638 | ifthen21: ; preds = %tmp33 |
| 639 | call void @g1(i8* %arg3, i64 0, i64 0) | 639 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -662,7 +662,7 @@ tmp34: ; preds = %body5, %body4, %ifelse21, | |||
| 662 | br i1 %conv16, label %ifthen22, label %ifelse22 | 662 | br i1 %conv16, label %ifthen22, label %ifelse22 |
| 663 | 663 | ||
| 664 | ; CHECK: ifelse22: | 664 | ; CHECK: ifelse22: |
| 665 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(%array addrspace(1)* %.0191, i8 addrspace(1)* %.9), "struct-live"(%record* %17, %record* %1, %record* %5) ] | 665 | +; CHECK: %token171 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) [ "gc-live"(%array addrspace(1)* %.0196, i8 addrspace(1)* %.9), "struct-live"(%record* %17, %record* %1, %record* %5) ] |
| 666 | ; | 666 | ; |
| 667 | ifelse22: ; preds = %tmp34 | 667 | ifelse22: ; preds = %tmp34 |
| 668 | %conv18 = extractvalue { i64, i1 } %177, 0 | 668 | %conv18 = extractvalue { i64, i1 } %177, 0 |
| @@ -673,9 +673,9 @@ ifelse22: ; preds = %tmp34 | |||
| 673 | br i1 %icmpeq15, label %tmp31, label %tmp32 | 673 | br i1 %icmpeq15, label %tmp31, label %tmp32 |
| 674 | 674 | ||
| 675 | ; CHECK: ifthen22: | 675 | ; CHECK: ifthen22: |
| 676 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %1) ] | 676 | +; CHECK: %token174 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i64, i64)* @g1, i32 3, i32 0, i8* %arg3, i64 0, i64 0) [ "struct-live"(%record* %1) ] |
| 677 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %225) [ "struct-live"(%record* %1) ] | 677 | +; CHECK: %token176 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %206) [ "struct-live"(%record* %1) ] |
| 678 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %226) [ "gc-live"(i8 addrspace(1)* %226) ] | 678 | +; CHECK: %token178 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %207) |
| 679 | ; | 679 | ; |
| 680 | ifthen22: ; preds = %tmp34 | 680 | ifthen22: ; preds = %tmp34 |
| 681 | call void @g1(i8* %arg3, i64 0, i64 0) | 681 | call void @g1(i8* %arg3, i64 0, i64 0) |
| @@ -743,9 +743,9 @@ end1: ; preds = %tmp36, %body6 | |||
| 743 | br i1 %icmpeq18, label %tmp37, label %tmp38 | 743 | br i1 %icmpeq18, label %tmp37, label %tmp38 |
| 744 | 744 | ||
| 745 | ; CHECK: tmp37: | 745 | ; CHECK: tmp37: |
| 746 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) [ "struct-live"(%record* %17) ] | 746 | +; CHECK: %token180 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8*, i32)* @g5, i32 2, i32 0, i8* %arg3, i32 40) [ "struct-live"(%record* %17) ] |
| 747 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, %record addrspace(1)*)* @g10, i32 3, i32 0, i8 addrspace(1)* %242, i8 addrspace(1)* null, %record addrspace(1)* %243) [ "gc-live"(i8 addrspace(1)* %242), "struct-live"(%record* %17) ] | 747 | +; CHECK: %token182 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, i8 addrspace(1)*, %record addrspace(1)*)* @g10, i32 3, i32 0, i8 addrspace(1)* %222, i8 addrspace(1)* null, %record addrspace(1)* %223) [ "gc-live"(i8 addrspace(1)* %222), "struct-live"(%record* %17) ] |
| 748 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %244) [ "gc-live"(i8 addrspace(1)* %244) ] | 748 | +; CHECK: %token184 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g3, i32 1, i32 0, i8 addrspace(1)* %224) |
| 749 | ; | 749 | ; |
| 750 | tmp37: ; preds = %end1 | 750 | tmp37: ; preds = %end1 |
| 751 | %196 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) | 751 | %196 = call i8 addrspace(1)* @g5(i8* %arg3, i32 40) |
| @@ -44,7 +44,7 @@ entry: | |||
| 44 | ; CHECK-NEXT: %.sroa.0.0.insert.insert14 = or i64 %.sroa.0.0.insert.mask13, %.sroa.0.0.insert.ext12 | 44 | ; CHECK-NEXT: %.sroa.0.0.insert.insert14 = or i64 %.sroa.0.0.insert.mask13, %.sroa.0.0.insert.ext12 |
| 45 | ; CHECK-NEXT: %.fca.0.insert = insertvalue %record poison, i64 %.sroa.0.0.insert.insert14, 0 | 45 | ; CHECK-NEXT: %.fca.0.insert = insertvalue %record poison, i64 %.sroa.0.0.insert.insert14, 0 |
| 46 | ; CHECK-NEXT: %.fca.1.insert = insertvalue %record %.fca.0.insert, i8 addrspace(1)* %arg0.fca.1.extract, 1 | 46 | ; CHECK-NEXT: %.fca.1.insert = insertvalue %record %.fca.0.insert, i8 addrspace(1)* %arg0.fca.1.extract, 1 |
| 47 | -; CHECK-NEXT: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) | 47 | +; CHECK-NEXT: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void ()* @g0, i32 0, i32 0) |
| 48 | ; | 48 | ; |
| 49 | tmp1: | 49 | tmp1: |
| 50 | %3 = load %record, %record* %0 | 50 | %3 = load %record, %record* %0 |
| @@ -54,7 +54,7 @@ tmp1: | |||
| 54 | ; CHECK: tmp2: | 54 | ; CHECK: tmp2: |
| 55 | ; CHECK-NEXT: %.sroa.0.sroa.0.0.sroa_cast33 = bitcast i8* %.sroa.0.sroa.0 to i1* | 55 | ; CHECK-NEXT: %.sroa.0.sroa.0.0.sroa_cast33 = bitcast i8* %.sroa.0.sroa.0 to i1* |
| 56 | ; CHECK-NEXT: %.sroa.0.sroa.0.0..sroa.0.sroa.0.0..sroa.0.0. = load i1, i1* %.sroa.0.sroa.0.0.sroa_cast33, align 8 | 56 | ; CHECK-NEXT: %.sroa.0.sroa.0.0..sroa.0.sroa.0.0..sroa.0.0. = load i1, i1* %.sroa.0.sroa.0.0.sroa_cast33, align 8 |
| 57 | -; CHECK-NEXT: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g1, i32 2, i32 0, %record addrspace(1)* %arg2, i8 addrspace(1)* null) [ "gc-live"(%record %arg0, i8 addrspace(1)* %arg1, %record addrspace(1)* %arg2) ] | 57 | +; CHECK-NEXT: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g1, i32 2, i32 0, %record addrspace(1)* %arg2, i8 addrspace(1)* null) [ "gc-live"(%record %arg0) ] |
| 58 | ; | 58 | ; |
| 59 | tmp2: | 59 | tmp2: |
| 60 | %4 = bitcast %record* %0 to i1* | 60 | %4 = bitcast %record* %0 to i1* |
| @@ -29,7 +29,7 @@ define %record @foo(%record addrspace(1)* %ptr2, i8 addrspace(1)* %ptr1, %record | |||
| 29 | ; CHECK-NEXT: %f.select = select i1 %b1, %record addrspace(1)* %f.cast, %record addrspace(1)* %g.cast | 29 | ; CHECK-NEXT: %f.select = select i1 %b1, %record addrspace(1)* %f.cast, %record addrspace(1)* %g.cast |
| 30 | ; CHECK-NEXT: %f.select.sroa.gep9 = getelementptr inbounds %record, %record addrspace(1)* %f.select, i32 0, i32 1 | 30 | ; CHECK-NEXT: %f.select.sroa.gep9 = getelementptr inbounds %record, %record addrspace(1)* %f.select, i32 0, i32 1 |
| 31 | ; CHECK-NEXT: %f.select.sroa.gep = getelementptr inbounds %record, %record addrspace(1)* %f.select, i32 0, i32 0 | 31 | ; CHECK-NEXT: %f.select.sroa.gep = getelementptr inbounds %record, %record addrspace(1)* %f.select, i32 0, i32 0 |
| 32 | -; CHECK-NEXT: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record addrspace(1)* %ptr2, i8 addrspace(1)* %ptr1) [ "gc-live"(%record addrspace(1)* %ptr2, i8 addrspace(1)* %ptr1), "struct-live"(%record* %f, %record* %g) ] | 32 | +; CHECK-NEXT: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record addrspace(1)* %ptr2, i8 addrspace(1)* %ptr1) [ "gc-live"(%record addrspace(1)* %ptr2, i8 addrspace(1)* %ptr1), "struct-live"(%record* %f, %record* %g) ] |
| 33 | ; | 33 | ; |
| 34 | entry: | 34 | entry: |
| 35 | %f = alloca %record | 35 | %f = alloca %record |
| @@ -64,7 +64,7 @@ else: | |||
| 64 | ; CHECK-NEXT: %g.loaded.fca.1.gep = getelementptr inbounds %record, %record addrspace(1)* %g.select, i32 0, i32 1 | 64 | ; CHECK-NEXT: %g.loaded.fca.1.gep = getelementptr inbounds %record, %record addrspace(1)* %g.select, i32 0, i32 1 |
| 65 | ; CHECK-NEXT: %g.loaded.fca.1.load = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %g.loaded.fca.1.gep, align 8 | 65 | ; CHECK-NEXT: %g.loaded.fca.1.load = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %g.loaded.fca.1.gep, align 8 |
| 66 | ; CHECK-NEXT: %g.loaded.fca.1.insert = insertvalue %record %g.loaded.fca.0.insert, i8 addrspace(1)* %g.loaded.fca.1.load, 1 | 66 | ; CHECK-NEXT: %g.loaded.fca.1.insert = insertvalue %record %g.loaded.fca.0.insert, i8 addrspace(1)* %g.loaded.fca.1.load, 1 |
| 67 | -; CHECK-NEXT: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, %record (%record, %record)* @g1, i32 2, i32 0, %record %f.loaded.fca.1.insert, %record %g.loaded.fca.1.insert) [ "gc-live"(%record %f.loaded.fca.1.insert, %record %g.loaded.fca.1.insert) ] | 67 | +; CHECK-NEXT: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, %record (%record, %record)* @g1, i32 2, i32 0, %record %f.loaded.fca.1.insert, %record %g.loaded.fca.1.insert) [ "gc-live"(%record %f.loaded.fca.1.insert) ] |
| 68 | ; | 68 | ; |
| 69 | exit: | 69 | exit: |
| 70 | %f.phi = phi %record addrspace(1)* [ %f.cast, %then ], [ %f.select, %else ] | 70 | %f.phi = phi %record addrspace(1)* [ %f.cast, %then ], [ %f.select, %else ] |
| @@ -9,10 +9,10 @@ declare void @g1(%record addrspace(1)* %arg1, i8 addrspace(1)* %arg0, i64 %arg2) | |||
| 9 | define void @foo(%record addrspace(1)* %arg1, i8 addrspace(1)* %arg0, i64 %arg2, i64 %arg3) #0 gc "cangjie" { | 9 | define void @foo(%record addrspace(1)* %arg1, i8 addrspace(1)* %arg0, i64 %arg2, i64 %arg3) #0 gc "cangjie" { |
| 10 | ; CHECK-LABEL: @foo( | 10 | ; CHECK-LABEL: @foo( |
| 11 | ; CHECK: entry: | 11 | ; CHECK: entry: |
| 12 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, %record addrspace(1)* (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g0, i32 3, i32 0, %record addrspace(1)* %arg1, i8 addrspace(1)* null, i64 %arg2) [ "gc-live"(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1) ] | 12 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, %record addrspace(1)* (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g0, i32 3, i32 0, %record addrspace(1)* %arg1, i8 addrspace(1)* null, i64 %arg2) [ "gc-live"(%record addrspace(1)* %arg1, i8 addrspace(1)* %arg0) ] |
| 13 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, %record addrspace(1)* (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g0, i32 3, i32 0, %record addrspace(1)* %arg1.reloc.casted, i8 addrspace(1)* null, i64 %arg3) [ "gc-live"(i8 addrspace(1)* %arg0.reloc, %record addrspace(1)* %arg1.reloc.casted), "struct-live"(%record addrspace(1)** %temp) ] | 13 | +; CHECK: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, %record addrspace(1)* (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g0, i32 3, i32 0, %record addrspace(1)* %arg1.reloc.casted, i8 addrspace(1)* null, i64 %arg3) [ "struct-live"(%record addrspace(1)** %temp) ] |
| 14 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g1, i32 3, i32 0, %record addrspace(1)* %1, i8 addrspace(1)* null, i64 %arg2) [ "gc-live"(%record addrspace(1)* %1), "struct-live"(%record addrspace(1)** %temp) ] | 14 | +; CHECK: %token4 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g1, i32 3, i32 0, %record addrspace(1)* %1, i8 addrspace(1)* null, i64 %arg2) [ "struct-live"(%record addrspace(1)** %temp) ] |
| 15 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g1, i32 3, i32 0, %record addrspace(1)* %4, i8 addrspace(1)* null, i64 %arg2) [ "gc-live"(%record addrspace(1)* %4) ] | 15 | +; CHECK: %token6 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*, i64)* @g1, i32 3, i32 0, %record addrspace(1)* %2, i8 addrspace(1)* null, i64 %arg2) |
| 16 | ; | 16 | ; |
| 17 | entry: | 17 | entry: |
| 18 | %temp = alloca %record addrspace(1)* | 18 | %temp = alloca %record addrspace(1)* |
| @@ -17,7 +17,7 @@ entry: | |||
| 17 | br label %body | 17 | br label %body |
| 18 | 18 | ||
| 19 | ; CHECK: body: | 19 | ; CHECK: body: |
| 20 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*)* @g0, i32 2, i32 0, i8 addrspace(1)* %a, %record addrspace(1)* %arg) [ "gc-live"(%record addrspace(1)* %arg, i8 addrspace(1)* %a) ] | 20 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*)* @g0, i32 2, i32 0, i8 addrspace(1)* %a, %record addrspace(1)* %arg) [ "gc-live"(%record addrspace(1)* %arg) ] |
| 21 | ; | 21 | ; |
| 22 | body: ; preds = %entry | 22 | body: ; preds = %entry |
| 23 | call void @g0(i8 addrspace(1)* %a, %record addrspace(1)* %arg) | 23 | call void @g0(i8 addrspace(1)* %a, %record addrspace(1)* %arg) |
| @@ -42,9 +42,9 @@ tmpend: ; preds = %tmp1, %tmp2 | |||
| 42 | br i1 %conv, label %ifthen, label %ifelse | 42 | br i1 %conv, label %ifthen, label %ifelse |
| 43 | 43 | ||
| 44 | ; CHECK: ifthen: | 44 | ; CHECK: ifthen: |
| 45 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*)* @g1, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %9) [ "struct-live"(%record* %0) ] | 45 | +; CHECK: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*)* @g1, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %9) [ "struct-live"(%record* %0) ] |
| 46 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i1 (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %9) [ "struct-live"(%record* %0) ] | 46 | +; CHECK: %token4 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i1 (i8 addrspace(1)*, %record addrspace(1)*)* @g2, i32 2, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %9) [ "struct-live"(%record* %0) ] |
| 47 | -; CHECK: [[TOKEN:%.*]] = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*, i1)* @g3, i32 3, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %11, i1 %10) [ "struct-live"(%record* %0) ] | 47 | +; CHECK: %token6 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*, %record addrspace(1)*, i1)* @g3, i32 3, i32 0, i8 addrspace(1)* null, %record addrspace(1)* %11, i1 %10) [ "struct-live"(%record* %0) ] |
| 48 | ; | 48 | ; |
| 49 | ifthen: ; preds = %tmpend | 49 | ifthen: ; preds = %tmpend |
| 50 | %7 = add i32 %5, 1 | 50 | %7 = add i32 %5, 1 |
| @@ -30,9 +30,9 @@ body: ; preds = %entry | |||
| 30 | br i1 %icmpslt, label %ifthen, label %ifelse | 30 | br i1 %icmpslt, label %ifthen, label %ifelse |
| 31 | 31 | ||
| 32 | ; CHECK: ifthen: | 32 | ; CHECK: ifthen: |
| 33 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, i64)* @g0, i32 2, i32 0, i8 addrspace(1)* %10, i64 %13) [ "gc-live"(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1, i8 addrspace(1)* %10), "struct-live"(%record* %0) ] | 33 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, i8 addrspace(1)* (i8 addrspace(1)*, i64)* @g0, i32 2, i32 0, i8 addrspace(1)* %10, i64 %13) [ "gc-live"(%record addrspace(1)* %arg1, i8 addrspace(1)* %arg0), "struct-live"(%record* %0) ] |
| 34 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i8*, i64, i1)* @g1, i32 4, i32 0, i8* %18, i8* %19, i64 16, i1 false) [ "gc-live"(i8 addrspace(1)* %arg0.reloc, %record addrspace(1)* %arg1.reloc.casted), "struct-live"(%record* %0, %record* %1) ] | 34 | +; CHECK: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8*, i8*, i64, i1)* @g1, i32 4, i32 0, i8* %17, i8* %18, i64 16, i1 false) [ "gc-live"(%record addrspace(1)* %arg1.reloc.casted, i8 addrspace(1)* %arg0.reloc), "struct-live"(%record* %0, %record* %1) ] |
| 35 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*, i64, i64 addrspace(1)*)* @g2, i32 4, i32 0, %record addrspace(1)* %arg1.reloc4.casted, i8 addrspace(1)* %arg0.reloc3, i64 %add, i64 addrspace(1)* %24) [ "gc-live"(i8 addrspace(1)* %arg0.reloc3, %record addrspace(1)* %arg1.reloc4.casted, i64 addrspace(1)* %24) ] | 35 | +; CHECK: %token6 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*, i64, i64 addrspace(1)*)* @g2, i32 4, i32 0, %record addrspace(1)* %arg1.reloc3.casted, i8 addrspace(1)* %arg0.reloc4, i64 %add, i64 addrspace(1)* %23) |
| 36 | ; | 36 | ; |
| 37 | ifthen: ; preds = %body | 37 | ifthen: ; preds = %body |
| 38 | %8 = bitcast %record addrspace(1)* %arg1 to %object addrspace(1)* | 38 | %8 = bitcast %record addrspace(1)* %arg1 to %object addrspace(1)* |
| @@ -29,8 +29,8 @@ entry: | |||
| 29 | br i1 %5, label %ifelse, label %ifend | 29 | br i1 %5, label %ifelse, label %ifend |
| 30 | 30 | ||
| 31 | ; CHECK: ifelse: | 31 | ; CHECK: ifelse: |
| 32 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record addrspace(1)* %arg1, i8 addrspace(1)* null) [ "gc-live"(i8 addrspace(1)* %arg3, i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1) ] | 32 | +; CHECK: %token = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record addrspace(1)* %arg1, i8 addrspace(1)* null) [ "gc-live"(i8 addrspace(1)* %arg3) ] |
| 33 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g1, i32 1, i32 0, i8 addrspace(1)* %arg3.reloc) [ "gc-live"(i8 addrspace(1)* %arg3.reloc) ] | 33 | +; CHECK: %token2 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (i8 addrspace(1)*)* @g1, i32 1, i32 0, i8 addrspace(1)* %arg3.reloc) [ "gc-live"(i8 addrspace(1)* %arg3.reloc) ] |
| 34 | ; | 34 | ; |
| 35 | ifelse: ; preds = %body | 35 | ifelse: ; preds = %body |
| 36 | call void @g0(%record addrspace(1)* %arg1, i8 addrspace(1)* null) | 36 | call void @g0(%record addrspace(1)* %arg1, i8 addrspace(1)* null) |
| @@ -38,7 +38,7 @@ ifelse: ; preds = %body | |||
| 38 | ret i8 addrspace(1)* %arg3 | 38 | ret i8 addrspace(1)* %arg3 |
| 39 | 39 | ||
| 40 | ; CHECK: ifend: | 40 | ; CHECK: ifend: |
| 41 | -; CHECK: call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record addrspace(1)* %arg1, i8 addrspace(1)* %8) [ "gc-live"(i8 addrspace(1)* %8, i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1) ] | 41 | +; CHECK: %token5 = call token (...) @llvm.cj.gc.statepoint(i64 0, i32 0, void (%record addrspace(1)*, i8 addrspace(1)*)* @g0, i32 2, i32 0, %record addrspace(1)* %arg1, i8 addrspace(1)* %8) [ "gc-live"(i8 addrspace(1)* %8) ] |
| 42 | ; | 42 | ; |
| 43 | ifend: ; preds = %body | 43 | ifend: ; preds = %body |
| 44 | %6 = bitcast %record addrspace(1)* %arg1 to %array addrspace(1)* | 44 | %6 = bitcast %record addrspace(1)* %arg1 to %array addrspace(1)* |


所以 这个地方是 相当于整个callsite的么? 是否是 最后读的时候是从 StartIdx , 要读这个callsite 整个root , 去看 整个序列是否含有重复的。最终想要的效果是 : ".Lstack_map.__CN7default8stackVal6Hv":
;StackSize: 80
#StackmapFormatType: bit map
#CalleeSaveReg: (0xc00=3072), x29(fp), x30(lr), offsets(without sign): [0, 8]
#StackMapItem nums:3
.quad -6759567686414564084
.byte 4
.long Ltmp20-"__CN7default8stackVal6Hv"
;[RegIdx: -1, SlotIdx: 0, LNIdx: 0, DerivedStartIdx: 0]
.byte 82
.byte 0
.long Ltmp21-"__CN7default8stackVal6Hv"
;[RegIdx: -1, SlotIdx: 0, LNIdx: 0, DerivedStartIdx: 1]
.byte 146
.byte 0
.long Ltmp22-"__CN7default8stackVal6Hv"
;[RegIdx: -1, SlotIdx: 2, LNIdx: 0, DerivedStartIdx: 2]
.byte 214
.byte 0
;RegNums: 0
#SlotsNums: 3
#Idx[0]: BaseOffset: -32, SlotBits: 0x1[ -32 ]
#Idx[1]: BaseOffset: -24, SlotBits: 0x1[ -24 ]
#Idx[2]: BaseOffset: -32, SlotBits: 0x3[ -32 -40 ]
;LineNumbersNums: 1
#Idx[0]: 6
;DerivedInfoNums: 4
#Idx[0]: RegIdx: -1, SlotIdx: 1
#Idx[1]: RegIdx: -1, SlotIdx: 1
#Idx[2]: RegIdx: -1, SlotIdx: 1
#Idx[3]: RegIdx: -1, SlotIdx: -1
.quad -7437729444484971760
.byte 136
.byte 8
.byte 0
合并 .long Ltmp21 与 .long Ltmp20 的 DerivedStartIdx: 1] ?