已合并
fix: tail call opt, stackmap opt #583
jiadiliu创建于 7月24日
fix: tail call opt, stackmap opt #583
已合并
jiadiliu创建于 7月24日
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;
睡觉对我很重要

所以 这个地方是 相当于整个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] ?

likedislike
165 167 
166 MaxBitsInfo MaxBits;168 MaxBitsInfo MaxBits;
167 // unordered_map<regNo, bitIdx>, regNo can be used to find callee saved reg169 // 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 
172class DataEncoder {187class DataEncoder {
@@ -25,6 +25,12 @@ enum {
25};25};
26} // end namespace TargetOpcode26} // 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 supposed34/// Check whether the given Opcode is a generic opcode that is not supposed
29/// to appear after ISel.35/// to appear after ISel.
30inline bool isPreISelGenericOpcode(unsigned Opcode) {36inline 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.
158HANDLE_TARGET_OPCODE(STATEPOINT)158HANDLE_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 to164/// 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 the165/// 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+}
1289def LOAD_STACK_GUARD : StandardPseudoInstruction {1301def 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 LowerSTATEPOINT4195 // 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#include "llvm/CodeGen/StackMaps.h"30#include "llvm/CodeGen/StackMaps.h"
31#include "llvm/CodeGen/TargetInstrInfo.h"31#include "llvm/CodeGen/TargetInstrInfo.h"
32#include "llvm/CodeGen/TargetLowering.h"32#include "llvm/CodeGen/TargetLowering.h"
33+#include "llvm/CodeGen/TargetOpcodes.h"
33#include "llvm/CodeGen/TargetRegisterInfo.h"34#include "llvm/CodeGen/TargetRegisterInfo.h"
34#include "llvm/CodeGen/TargetSubtargetInfo.h"35#include "llvm/CodeGen/TargetSubtargetInfo.h"
35#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"36#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
@@ -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::STATEPOINT1982+ return !isStatepointOpcode(MI->getOpcode())
1982 ? false1983 ? 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 marks2093 // 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::STATEPOINT2096+ return !isStatepointOpcode(MI->getOpcode())
2096 ? false2097 ? false
2097 : StatepointOpers(MI).getID() ==2098 : StatepointOpers(MI).getID() ==
2098 Cangjie::CJStatepointID::SafepointStub;2099 Cangjie::CJStatepointID::SafepointStub;
@@ -25,6 +25,7 @@
25#include "llvm/CodeGen/MachineRegisterInfo.h"25#include "llvm/CodeGen/MachineRegisterInfo.h"
26#include "llvm/CodeGen/Passes.h"26#include "llvm/CodeGen/Passes.h"
27#include "llvm/CodeGen/TargetInstrInfo.h"27#include "llvm/CodeGen/TargetInstrInfo.h"
28+#include "llvm/CodeGen/TargetOpcodes.h"
28#include "llvm/IR/Instructions.h"29#include "llvm/IR/Instructions.h"
29#include "llvm/MC/MCAsmInfo.h"30#include "llvm/MC/MCAsmInfo.h"
30#include "llvm/Support/Debug.h"31#include "llvm/Support/Debug.h"
@@ -767,7 +768,7 @@ void CJStackPointerInserter::getAnalysisUsage(AnalysisUsage &AU) const {
767}768}
768 769 
769bool CJStackPointerInserter::needRewriteCall(MachineInstr &MI) {770bool 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#include "llvm/CodeGen/MachineFunctionPass.h"26#include "llvm/CodeGen/MachineFunctionPass.h"
27#include "llvm/CodeGen/StackMaps.h"27#include "llvm/CodeGen/StackMaps.h"
28#include "llvm/CodeGen/TargetInstrInfo.h"28#include "llvm/CodeGen/TargetInstrInfo.h"
29+#include "llvm/CodeGen/TargetOpcodes.h"
29#include "llvm/IR/Statepoint.h"30#include "llvm/IR/Statepoint.h"
30#include "llvm/InitializePasses.h"31#include "llvm/InitializePasses.h"
31#include "llvm/Support/Debug.h"32#include "llvm/Support/Debug.h"
@@ -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 only547 // 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 instructions548 // 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 hoping552 // 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 through818 // For that to work we need to untie def and use to pass it through
819 // foldMemoryOperand and signal foldPatchpoint that it is allowed to819 // 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 such892/// 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.
894static bool hasLiveThroughUse(const MachineInstr *MI, Register Reg) {894static 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 of314 // 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 ptr655 // 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 TiedMax1095 // 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 passed1132 // 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 
1471bool MachineInstr::hasComplexRegisterTies() const {1472bool 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 only1447 // implementation other than historical accident. The only
1448 // remaining difference is the unconditional use of the stack1448 // 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 reg205 // 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#include "llvm/ADT/SmallSet.h"22#include "llvm/ADT/SmallSet.h"
23#include "llvm/ADT/SmallVector.h"23#include "llvm/ADT/SmallVector.h"
24#include "llvm/ADT/Statistic.h"24#include "llvm/ADT/Statistic.h"
25+#include "llvm/ADT/Triple.h"
26+#include "llvm/CodeGen/Analysis.h"
25#include "llvm/CodeGen/FunctionLoweringInfo.h"27#include "llvm/CodeGen/FunctionLoweringInfo.h"
26#include "llvm/CodeGen/GCMetadata.h"28#include "llvm/CodeGen/GCMetadata.h"
27#include "llvm/CodeGen/ISDOpcodes.h"29#include "llvm/CodeGen/ISDOpcodes.h"
@@ -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 the335+namespace {
334-/// call node. Also update NodeMap so that getValue(statepoint) will336+struct StatepointCallLoweringResult {
335-/// reference lowered call result337+ 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 not354+ // Get a call instruction from the call sequence chain. The following code is
345- // allowed. The following code is essentially reverse engineering X86's355+ // 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 
376static MachineMemOperand* getMachineMemOperand(MachineFunction &MF,393static 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 statepoint952 // 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_END959 // 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 used1083 // 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 node1171+ 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 must1179 // 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 needed1329 // 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't127 // 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`t231 // 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 else930 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 info961 // 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) {
1015void StackMaps::recordStatepoint(const MCSymbol &L, const MachineInstr &MI,1015void 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 the1019 // 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#include "llvm/CodeGen/MachineRegisterInfo.h"17#include "llvm/CodeGen/MachineRegisterInfo.h"
18#include "llvm/CodeGen/TargetFrameLowering.h"18#include "llvm/CodeGen/TargetFrameLowering.h"
19#include "llvm/CodeGen/TargetSubtargetInfo.h"19#include "llvm/CodeGen/TargetSubtargetInfo.h"
20+#include "llvm/CodeGen/TargetOpcodes.h"
20#include "llvm/IR/Attributes.h"21#include "llvm/IR/Attributes.h"
21#include "llvm/IR/CallingConv.h"22#include "llvm/IR/CallingConv.h"
22#include "llvm/IR/Function.h"23#include "llvm/IR/Function.h"
@@ -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 not1207 // Used for spills inserted by StatepointLowering. This codepath is not
1208 // used for patchpoints/stackmaps at all, for these spilling is done via1208 // 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, and1229 // 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#include "llvm/CodeGen/MachineModuleInfoImpls.h"41#include "llvm/CodeGen/MachineModuleInfoImpls.h"
42#include "llvm/CodeGen/MachineOperand.h"42#include "llvm/CodeGen/MachineOperand.h"
43#include "llvm/CodeGen/StackMaps.h"43#include "llvm/CodeGen/StackMaps.h"
44+#include "llvm/CodeGen/TargetOpcodes.h"
44#include "llvm/Support/CodeGen.h"45#include "llvm/Support/CodeGen.h"
45#include "llvm/CodeGen/TargetRegisterInfo.h"46#include "llvm/CodeGen/TargetRegisterInfo.h"
46#include "llvm/IR/DataLayout.h"47#include "llvm/IR/DataLayout.h"
@@ -1357,6 +1358,8 @@ void AArch64AsmPrinter::emitGcStateCheck() {
1357void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,1358void 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 opcode1363 // 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 intrinsic1385 // 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// .LNewArrayFin2166// .LNewArrayFin
2158void AArch64AsmPrinter::emitCJNewArrayFastPath(const MachineInstr &MI,2167void 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/uses2525 // 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 at2527 // has implicit def. This def is early-clobber as it will be set at
@@ -28,6 +28,7 @@
28#include "llvm/CodeGen/MachineOperand.h"28#include "llvm/CodeGen/MachineOperand.h"
29#include "llvm/CodeGen/MachineRegisterInfo.h"29#include "llvm/CodeGen/MachineRegisterInfo.h"
30#include "llvm/CodeGen/StackMaps.h"30#include "llvm/CodeGen/StackMaps.h"
31+#include "llvm/CodeGen/TargetOpcodes.h"
31#include "llvm/CodeGen/TargetRegisterInfo.h"32#include "llvm/CodeGen/TargetRegisterInfo.h"
32#include "llvm/CodeGen/TargetSubtargetInfo.h"33#include "llvm/CodeGen/TargetSubtargetInfo.h"
33#include "llvm/IR/DebugInfoMetadata.h"34#include "llvm/IR/DebugInfoMetadata.h"
@@ -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 call92 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 emitted194 // No patch bytes means a normal call inst is emitted
@@ -25,6 +25,7 @@
25#include "llvm/CodeGen/MachineRegisterInfo.h"25#include "llvm/CodeGen/MachineRegisterInfo.h"
26#include "llvm/CodeGen/RegisterScavenging.h"26#include "llvm/CodeGen/RegisterScavenging.h"
27#include "llvm/CodeGen/TargetFrameLowering.h"27#include "llvm/CodeGen/TargetFrameLowering.h"
28+#include "llvm/CodeGen/TargetOpcodes.h"
28#include "llvm/IR/DebugInfoMetadata.h"29#include "llvm/IR/DebugInfoMetadata.h"
29#include "llvm/IR/DiagnosticInfo.h"30#include "llvm/IR/DiagnosticInfo.h"
30#include "llvm/IR/Function.h"31#include "llvm/IR/Function.h"
@@ -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 at36488 // 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#include "llvm/CodeGen/MachineModuleInfoImpls.h"31#include "llvm/CodeGen/MachineModuleInfoImpls.h"
32#include "llvm/CodeGen/MachineOperand.h"32#include "llvm/CodeGen/MachineOperand.h"
33#include "llvm/CodeGen/StackMaps.h"33#include "llvm/CodeGen/StackMaps.h"
34+#include "llvm/CodeGen/TargetOpcodes.h"
34#include "llvm/IR/DataLayout.h"35#include "llvm/IR/DataLayout.h"
35#include "llvm/IR/GlobalValue.h"36#include "llvm/IR/GlobalValue.h"
36#include "llvm/IR/Mangler.h"37#include "llvm/IR/Mangler.h"
@@ -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 opcode1594 // 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 target1633 // Otherwise, we'll need a scratch register to hold the target
1626 // address. You'll fail asserts during load & relocation if this1634 // 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 target1643 // Otherwise, we'll need a scratch register to hold the target
1635 // immediate. You'll fail asserts during load & relocation if this1644 // 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// LNewArrayFin3452// LNewArrayFin
3440void X86AsmPrinter::emitCJNewArrayFastPath(const MachineInstr &MI,3453void 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#endif291#endif
292 292 
293-// Conservatively identifies any definitions which might be live at the293+// Conservatively identifies any definitions which might be live across the
294-// given instruction. The analysis is performed immediately before the294+// given parse point. For statepoint insertion we care about values that remain
295-// given instruction. Values defined by that instruction are not considered295+// 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.
297void GCLiveAnalysis::analyzeParsePointLiveness(CallBase *Call,297void 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#endif437#endif
438}438}
439 439 
440-/// Given results from the dataflow liveness computation, find the set of live440+/// 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.
442void GCLiveAnalysis::findLiveSetAtInst(Instruction *Inst,443void 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's455+ // Liveness for a parse point is defined at the program point immediately
455- // call result is not live (normal), nor are it's arguments456+ // after the call. This trims values that are consumed only by the current
456- // (unless they're used again later). This adjustment is457+ // call and are dead afterwards.
457- // specifically what we need to relocate458+ computeLiveInValues(BI, Inst->getIterator().getReverse(), LiveOut);
睡觉对我很重要

LGTM

likedislike
458- computeLiveInValues(BI, ++Inst->getIterator().getReverse(), LiveOut);
459 LiveOut.remove(Inst);459 LiveOut.remove(Inst);
睡觉对我很重要

所以这个地方 其实是不是可以删除的

likedislike
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 中, 是这样么

likedislike
jiadiliu
24 天前 评论:
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"
7define void @test() "frame-pointer"="all" gc "statepoint-example" {7define void @test() "frame-pointer"="all" gc "statepoint-example" {
8entry:8entry:
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 $lr10+; 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 void11 ret void
12}12}
13 13 
@@ -125,10 +125,9 @@ define void @test_void_vararg() gc "statepoint-example" {
125; CHECK-NEXT: .cfi_offset w30, -16125; CHECK-NEXT: .cfi_offset w30, -16
126; CHECK-NEXT: mov w0, #42126; CHECK-NEXT: mov w0, #42
127; CHECK-NEXT: mov w1, #43127; CHECK-NEXT: mov w1, #43
128-; CHECK-NEXT: bl varargf
129-; CHECK-NEXT: .Ltmp6:
130; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload128; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
131-; CHECK-NEXT: ret129+; CHECK-NEXT: b varargf
130+; CHECK-NEXT: .Ltmp6:
132; Check a statepoint wrapping a *void* returning vararg function works131; Check a statepoint wrapping a *void* returning vararg function works
133entry:132entry:
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 @@
8declare void @cj_stack_grow()8declare void @cj_stack_grow()
9 9 
10define 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" {10define 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_fp20+; 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_fp22; 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: 124+; CHECK: #RegNums: 0
25-; CHECK: #Idx[0]: (0x236=566), rdx, rcx, rsi, rdi, r925+; CHECK: #SlotsNums: 2
26-; CHECK: #SlotsNums: 126+; 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: 028; CHECK: #LineNumbersNums: 0
29; CHECK: #DerivedInfoNums: 029; CHECK: #DerivedInfoNums: 0
30entry:30entry:
@@ -45,4 +45,4 @@ body:
45; Function Attrs: argmemonly nocallback nofree nounwind willreturn writeonly45; Function Attrs: argmemonly nocallback nofree nounwind willreturn writeonly
46declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #146declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #1
47declare void @CJ_MCC_StackCheck()47declare 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 16124; CHECK-NEXT: .cfi_def_cfa_offset 16
125; CHECK-NEXT: movl $42, %edi125; CHECK-NEXT: movl $42, %edi
126; CHECK-NEXT: movl $43, %esi126; CHECK-NEXT: movl $43, %esi
127-; CHECK-NEXT: callq varargf@PLT127+; CHECK-NEXT: addq $8, %rsp
128-; CHECK-NEXT: .Ltmp6:
129-; CHECK-NEXT: popq %rax
130; CHECK-NEXT: .cfi_def_cfa_offset 8128; CHECK-NEXT: .cfi_def_cfa_offset 8
131-; CHECK-NEXT: retq129+; CHECK-NEXT: jmp varargf@PLT # TAILCALL
130+; CHECK-NEXT: .Ltmp6:
132; Check a statepoint wrapping a *ptr returning vararg function works131; Check a statepoint wrapping a *ptr returning vararg function works
133entry:132entry:
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 %rax65; CHECK-NEXT: pushq %rax
66; CHECK-NEXT: .cfi_def_cfa_offset 1666; CHECK-NEXT: .cfi_def_cfa_offset 16
67; CHECK-NEXT: movq %rdi, (%rsp)67; CHECK-NEXT: movq %rdi, (%rsp)
68-; CHECK-NEXT: callq f@PLT68+; CHECK-NEXT: addq $8, %rsp
69-; CHECK-NEXT: .Ltmp2:
70-; CHECK-NEXT: popq %rax
71; CHECK-NEXT: .cfi_def_cfa_offset 869; CHECK-NEXT: .cfi_def_cfa_offset 8
72-; CHECK-NEXT: retq70+; 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 void74 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 %rax81; CHECK-NEXT: pushq %rax
83; CHECK-NEXT: .cfi_def_cfa_offset 1682; CHECK-NEXT: .cfi_def_cfa_offset 16
84-; CHECK-NEXT: callq f@PLT83+; CHECK-NEXT: addq $8, %rsp
85-; CHECK-NEXT: .Ltmp3:
86-; CHECK-NEXT: popq %rax
87; CHECK-NEXT: .cfi_def_cfa_offset 884; CHECK-NEXT: .cfi_def_cfa_offset 8
88-; CHECK-NEXT: retq85+; 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 void89 ret void
@@ -68,7 +68,7 @@ declare void @"_ZN11std$FS$core18NoneValueException6<init>Ev"(i8 addrspace(1)*)
68declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1)68declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1)
69declare void @llvm.memset.p0i8.i64(i8*, i8, i64, i1)69declare 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 
73define 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 {73define 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 {
74entry:74entry:
@@ -9,7 +9,7 @@ entry:
9 %r = alloca %struct9 %r = alloca %struct
10 br label %bb010 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;
14bb0:14bb0:
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 %bb222 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;
26bb2:26bb2:
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 %end14 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;
19for: ; preds = %entry, %for19for: ; 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 %end26 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;
31end: ; preds = %entry, %for31end: ; 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 %body119 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;
25body1: ; preds = %entry25body1: ; preds = %entry
26 %sub = sub i64 %index, 126 %sub = sub i64 %index, 1
@@ -41,7 +41,7 @@ body2: ; preds = %ifthen2, %body1
41 br i1 %icmpsge, label %ifthen1, label %ifelse141 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;
46ifthen1: ; preds = %body246ifthen1: ; preds = %body2
47 %10 = load i64, i64* %447 %10 = load i64, i64* %4
@@ -75,7 +75,7 @@ ifthen2: ; preds = %tmpend1
75 br label %body275 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;
80ifelse2: ; preds = %tmpend180ifelse2: ; preds = %tmpend1
81 %17 = load i64, i64* %481 %17 = load i64, i64* %4
@@ -107,7 +107,7 @@ tmpend2: ; preds = %tmp3, %tmp4
107 br i1 %conv8, label %ifthen3, label %ifelse3107 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;
112ifthen3: ; preds = %tmpend2112ifthen3: ; 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 %body163 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;
68body1: ; preds = %start168body1: ; 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 %tmpend174 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;
79tmp1: ; preds = %body179tmp1: ; 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 %ifend195 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;
101ifend1: ; preds = %ifelse1101ifend1: ; preds = %ifelse1
102 %38 = getelementptr inbounds %record2, %record2 addrspace(1)* %arg3, i32 0, i32 0102 %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 %ifelse2116 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;
124ifthen2: ; preds = %ifend1124ifthen2: ; 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 %tmp4142 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;
148tmp4: ; preds = %ifthen2148tmp4: ; 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 void151 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;
156tmp3: ; preds = %ifthen2156tmp3: ; preds = %ifthen2
157 %55 = add i64 %54, 1157 %55 = add i64 %54, 1
@@ -61,7 +61,7 @@ entry:
61 br label %body161 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;
66body1: ; preds = %entry66body1: ; 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 %ifend176 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;
81ifend1: ; preds = %ifelse181ifend1: ; preds = %ifelse1
82 %30 = getelementptr inbounds %record, %record addrspace(1)* %arg1, i32 0, i32 182 %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 %ifelse295 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;
101ifthen2: ; preds = %ifend1101ifthen2: ; 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 %ifend2107 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;
112ifend2: ; preds = %ifelse2112ifend2: ; 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 %ifelse6195 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;
200ifthen6: ; preds = %tmpend4200ifthen6: ; 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 %ifend6205 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;
211ifend6: ; preds = %ifelse6211ifend6: ; preds = %ifelse6
212 %48 = load i64, i64* %23212 %48 = load i64, i64* %23
@@ -264,7 +264,7 @@ tmpend5: ; preds = %tmp10, %tmp9
264 br i1 %conv21, label %ifthen9, label %ifelse9264 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;
269ifthen9: ; preds = %tmpend5269ifthen9: ; 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 %tmp14293 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;
298tmp14: ; preds = %tmpend6298tmp14: ; 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 %ifelse11348 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;
353ifthen11: ; preds = %tmpend8353ifthen11: ; 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 %tmp20378 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;
383tmp20: ; preds = %tmpend9383tmp20: ; 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 %tmp22416 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;
421tmp22: ; preds = %ifend7421tmp22: ; preds = %ifend7
422 call void @g10(i8 addrspace(1)* %arg2)422 call void @g10(i8 addrspace(1)* %arg2)
423 unreachable423 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;
429tmp21: ; preds = %ifend7429tmp21: ; 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 %ifelse14475 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;
480ifthen14: ; preds = %ifend13480ifthen14: ; preds = %ifend13
481 %100 = getelementptr inbounds %record, %record addrspace(1)* %arg1, i32 0, i32 0481 %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 %ifelse15501 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;
506ifthen15: ; preds = %tmpend12506ifthen15: ; preds = %tmpend12
507 %107 = getelementptr inbounds %record, %record addrspace(1)* %arg1, i32 0, i32 0507 %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 %tmp26550 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;
555tmp26: ; preds = %end1555tmp26: ; preds = %end1
556 call void @g10(i8 addrspace(1)* %arg2)556 call void @g10(i8 addrspace(1)* %arg2)
557 unreachable557 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;
563tmp25: ; preds = %end1563tmp25: ; 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 %ifelse16578 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;
583ifthen16: ; preds = %tmp25583ifthen16: ; 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)
23define i64 @foo(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1, i64 %arg2, i8* %arg3) #0 gc "cangjie" {23define i64 @foo(i8 addrspace(1)* %arg0, %record addrspace(1)* %arg1, i64 %arg2, i8* %arg3) #0 gc "cangjie" {
24; CHECK-LABEL: foo24; 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;
28entry:28entry:
29 %0 = alloca %record29 %0 = alloca %record
@@ -85,9 +85,9 @@ ifelse3: ; preds = %ifthen1
85 br label %body185 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;
92ifthen3: ; preds = %ifthen192ifthen3: ; 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;
112ifthen5: ; preds = %body1112ifthen5: ; 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 %body2114 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;
119ifthen7: ; preds = %body1119ifthen7: ; 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 %body1123 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;
130ifthen8: ; preds = %ifthen7130ifthen8: ; 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 %ifelse10148 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;
155ifthen9: ; preds = %ifthen6155ifthen9: ; 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 %tmp2164 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;
171ifthen10: ; preds = %ifelse9171ifthen10: ; 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 unreachable176 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;
183tmp2: ; preds = %ifelse10183tmp2: ; 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 unreachable187 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;
193tmp1: ; preds = %ifelse10193tmp1: ; 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 8203; 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;
207tmp4: ; preds = %tmp1207tmp4: ; 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 16221; 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;
225tmp6: ; preds = %tmpend2225tmp6: ; 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 %tmpend3231 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;
236tmpend3: ; preds = %tmp5, %tmp6236tmpend3: ; 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 %tmp8243 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;
248tmp8: ; preds = %tmpend3248tmp8: ; 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 %tmp10260 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;
265tmp10: ; preds = %tmpend4265tmp10: ; 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 %tmpend5271 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;
276tmpend5: ; preds = %tmp9, %tmp10276tmpend5: ; 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 %tmpend7305 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;
312tmp13: ; preds = %ifelse16, %tmp12312tmp13: ; 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 %ifend11339 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;
346ifthen11: ; preds = %tmp15346ifthen11: ; 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 %ifelse12374 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;
379ifelse12: ; preds = %tmp20379ifelse12: ; preds = %tmp20
380 %conv25 = extractvalue { i64, i1 } %105, 0380 %conv25 = extractvalue { i64, i1 } %105, 0
@@ -384,9 +384,9 @@ ifelse12: ; preds = %tmp20
384 br i1 %conv8, label %ifthen13, label %ifend11384 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;
391ifthen12: ; preds = %tmp20391ifthen12: ; 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 unreachable396 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;
403ifthen13: ; preds = %ifelse12403ifthen13: ; 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 %ifelse15419 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;
426ifthen14: ; preds = %tmp19426ifthen14: ; 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 unreachable431 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;
438ifthen15: ; preds = %ifelse14438ifthen15: ; 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 %ifelse16454 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;
459ifelse16: ; preds = %tmp16459ifelse16: ; preds = %tmp16
460 %conv17 = extractvalue { i64, i1 } %118, 0460 %conv17 = extractvalue { i64, i1 } %118, 0
@@ -466,9 +466,9 @@ ifelse16: ; preds = %tmp16
466 br i1 %icmpeq6, label %tmp13, label %tmpend7466 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;
473ifthen16: ; preds = %tmp16473ifthen16: ; 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 %tmp38487 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;
494ifthen4: ; preds = %tmp11494ifthen4: ; 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 %tmp22530 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;
537ifthen17: ; preds = %ifthen2537ifthen17: ; 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 %tmp32602 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;
609tmp31: ; preds = %ifelse22, %tmp29609tmp31: ; 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 %body4631 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;
638ifthen21: ; preds = %tmp33638ifthen21: ; 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 %ifelse22662 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;
667ifelse22: ; preds = %tmp34667ifelse22: ; preds = %tmp34
668 %conv18 = extractvalue { i64, i1 } %177, 0668 %conv18 = extractvalue { i64, i1 } %177, 0
@@ -673,9 +673,9 @@ ifelse22: ; preds = %tmp34
673 br i1 %icmpeq15, label %tmp31, label %tmp32673 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;
680ifthen22: ; preds = %tmp34680ifthen22: ; 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 %tmp38743 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;
750tmp37: ; preds = %end1750tmp37: ; 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.ext1244; 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, 045; 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, 146; 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;
49tmp1:49tmp1:
50 %3 = load %record, %record* %050 %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 856; 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;
59tmp2:59tmp2:
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.cast29; 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 130; 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 031; 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;
34entry:34entry:
35 %f = alloca %record35 %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 164; 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 865; 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, 166; 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;
69exit:69exit:
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)
9define void @foo(%record addrspace(1)* %arg1, i8 addrspace(1)* %arg0, i64 %arg2, i64 %arg3) #0 gc "cangjie" {9define 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;
17entry:17entry:
18 %temp = alloca %record addrspace(1)*18 %temp = alloca %record addrspace(1)*
@@ -17,7 +17,7 @@ entry:
17 br label %body17 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;
22body: ; preds = %entry22body: ; 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 %ifelse42 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;
49ifthen: ; preds = %tmpend49ifthen: ; preds = %tmpend
50 %7 = add i32 %5, 150 %7 = add i32 %5, 1
@@ -30,9 +30,9 @@ body: ; preds = %entry
30 br i1 %icmpslt, label %ifthen, label %ifelse30 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;
37ifthen: ; preds = %body37ifthen: ; 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 %ifend29 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;
35ifelse: ; preds = %body35ifelse: ; 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)* %arg338 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;
43ifend: ; preds = %body43ifend: ; preds = %body
44 %6 = bitcast %record addrspace(1)* %arg1 to %array addrspace(1)*44 %6 = bitcast %record addrspace(1)* %arg1 to %array addrspace(1)*