llvm.org GIT mirror llvm / 5d6365c
[FastISel][AArch64] Use the correct register class to make the MI verifier happy. This is mostly achieved by providing the correct register class manually, because getRegClassFor always returns the GPR*AllRegClass for MVT::i32 and MVT::i64. Also cleanup the code to use the FastEmitInst_* method whenever possible. This makes sure that the operands' register class is properly constrained. For all the remaining cases this adds the missing constrainOperandRegClass calls for each operand. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216225 91177308-0d34-0410-b5e6-96231b3b80d8 Juergen Ributzka 5 years ago
28 changed file(s) with 188 addition(s) and 184 deletion(s). Raw diff Collapse all Expand all
246246 FuncInfo.StaticAllocaMap.find(AI);
247247
248248 if (SI != FuncInfo.StaticAllocaMap.end()) {
249 unsigned ResultReg = createResultReg(&AArch64::GPR64RegClass);
249 unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
250250 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADDXri),
251251 ResultReg)
252252 .addFrameIndex(SI->second)
270270 : &AArch64::GPR32RegClass;
271271 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
272272 unsigned ResultReg = createResultReg(RC);
273 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
274 TII.get(TargetOpcode::COPY), ResultReg)
275 .addReg(ZeroReg, getKillRegState(true));
273 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::COPY),
274 ResultReg).addReg(ZeroReg, getKillRegState(true));
276275 return ResultReg;
277276 }
278277
685684 // the alloca address into a register, set the base type back to register and
686685 // continue. This should almost never happen.
687686 if (ImmediateOffsetNeedsLowering && Addr.isFIBase()) {
688 unsigned ResultReg = createResultReg(&AArch64::GPR64RegClass);
687 unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
689688 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADDXri),
690689 ResultReg)
691690 .addFrameIndex(Addr.getFI())
697696
698697 if (RegisterOffsetNeedsLowering) {
699698 unsigned ResultReg = 0;
700 if (Addr.getReg()) {
701 ResultReg = createResultReg(&AArch64::GPR64RegClass);
702 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
703 TII.get(AArch64::ADDXrs), ResultReg)
704 .addReg(Addr.getReg())
705 .addReg(Addr.getOffsetReg())
706 .addImm(Addr.getShift());
707 } else
699 if (Addr.getReg())
700 ResultReg = FastEmitInst_rri(AArch64::ADDXrs, &AArch64::GPR64RegClass,
701 Addr.getReg(), /*TODO:IsKill=*/false,
702 Addr.getOffsetReg(), /*TODO:IsKill=*/false,
703 Addr.getShift());
704 else
708705 ResultReg = Emit_LSL_ri(MVT::i64, Addr.getOffsetReg(),
709706 /*Op0IsKill=*/false, Addr.getShift());
710707 if (!ResultReg)
751748 MIB.addFrameIndex(FI).addImm(Offset);
752749 } else {
753750 assert(Addr.isRegBase() && "Unexpected address kind.");
751 const MCInstrDesc &II = MIB->getDesc();
752 unsigned Idx = (Flags & MachineMemOperand::MOStore) ? 1 : 0;
753 Addr.setReg(
754 constrainOperandRegClass(II, Addr.getReg(), II.getNumDefs()+Idx));
755 Addr.setOffsetReg(
756 constrainOperandRegClass(II, Addr.getOffsetReg(), II.getNumDefs()+Idx+1));
754757 if (Addr.getOffsetReg()) {
755758 assert(Addr.getOffset() == 0 && "Unexpected offset");
756759 bool IsSigned = Addr.getExtendType() == AArch64_AM::SXTW ||
899902 };
900903 unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
901904 unsigned ResultReg;
902 if (WantResult)
903 ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
904 else
905 if (WantResult) {
906 const TargetRegisterClass *RC =
907 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
908 ResultReg = createResultReg(RC);
909 } else
905910 ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
906911
907 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
912 const MCInstrDesc &II = TII.get(Opc);
913 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
914 RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
915 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
908916 .addReg(LHSReg, getKillRegState(LHSIsKill))
909917 .addReg(RHSReg, getKillRegState(RHSIsKill));
910918
934942 };
935943 unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
936944 unsigned ResultReg;
937 if (WantResult)
938 ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
939 else
945 if (WantResult) {
946 const TargetRegisterClass *RC =
947 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
948 ResultReg = createResultReg(RC);
949 } else
940950 ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
941951
942 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
952 const MCInstrDesc &II = TII.get(Opc);
953 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
954 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
943955 .addReg(LHSReg, getKillRegState(LHSIsKill))
944956 .addImm(Imm)
945957 .addImm(getShifterImm(AArch64_AM::LSL, ShiftImm));
963975 };
964976 unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
965977 unsigned ResultReg;
966 if (WantResult)
967 ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
968 else
978 if (WantResult) {
979 const TargetRegisterClass *RC =
980 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
981 ResultReg = createResultReg(RC);
982 } else
969983 ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
970984
971 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
985 const MCInstrDesc &II = TII.get(Opc);
986 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
987 RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
988 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
972989 .addReg(LHSReg, getKillRegState(LHSIsKill))
973990 .addReg(RHSReg, getKillRegState(RHSIsKill))
974991 .addImm(getShifterImm(ShiftType, ShiftImm));
9921009 };
9931010 unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
9941011 unsigned ResultReg;
995 if (WantResult)
996 ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
997 else
1012 if (WantResult) {
1013 const TargetRegisterClass *RC =
1014 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1015 ResultReg = createResultReg(RC);
1016 } else
9981017 ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
9991018
1000 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1019 const MCInstrDesc &II = TII.get(Opc);
1020 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1021 RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1022 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
10011023 .addReg(LHSReg, getKillRegState(LHSIsKill))
10021024 .addReg(RHSReg, getKillRegState(RHSIsKill))
10031025 .addImm(getArithExtendImm(ExtType, ShiftImm));
12891311 SrcReg = ANDReg;
12901312 }
12911313 // Create the base instruction, then add the operands.
1292 MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1293 TII.get(Opc))
1294 .addReg(SrcReg);
1314 const MCInstrDesc &II = TII.get(Opc);
1315 SrcReg = constrainOperandRegClass(II, SrcReg, II.getNumDefs());
1316 MachineInstrBuilder MIB =
1317 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addReg(SrcReg);
12951318 AddLoadStoreOperands(Addr, MIB, MachineMemOperand::MOStore, ScaleFactor, MMO);
12961319
12971320 return true;
15161539 return false;
15171540
15181541 // Emit the indirect branch.
1519 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::BR))
1520 .addReg(AddrReg);
1542 const MCInstrDesc &II = TII.get(AArch64::BR);
1543 AddrReg = constrainOperandRegClass(II, AddrReg, II.getNumDefs());
1544 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addReg(AddrReg);
15211545
15221546 // Make sure the CFG is up-to-date.
15231547 for (unsigned i = 0, e = BI->getNumSuccessors(); i != e; ++i)
15641588 return false;
15651589
15661590 unsigned SelectOpc;
1591 const TargetRegisterClass *RC = nullptr;
15671592 switch (DestVT.SimpleTy) {
15681593 default: return false;
1569 case MVT::i32: SelectOpc = AArch64::CSELWr; break;
1570 case MVT::i64: SelectOpc = AArch64::CSELXr; break;
1571 case MVT::f32: SelectOpc = AArch64::FCSELSrrr; break;
1572 case MVT::f64: SelectOpc = AArch64::FCSELDrrr; break;
1594 case MVT::i32:
1595 SelectOpc = AArch64::CSELWr; RC = &AArch64::GPR32RegClass; break;
1596 case MVT::i64:
1597 SelectOpc = AArch64::CSELXr; RC = &AArch64::GPR64RegClass; break;
1598 case MVT::f32:
1599 SelectOpc = AArch64::FCSELSrrr; RC = &AArch64::FPR32RegClass; break;
1600 case MVT::f64:
1601 SelectOpc = AArch64::FCSELDrrr; RC = &AArch64::FPR64RegClass; break;
15731602 }
15741603
15751604 const Value *Cond = SI->getCondition();
15981627 if (!TrueReg || !FalseReg)
15991628 return false;
16001629
1601 unsigned ResultReg = createResultReg(TLI.getRegClassFor(DestVT));
1602 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SelectOpc),
1603 ResultReg)
1604 .addReg(TrueReg, getKillRegState(TrueIsKill))
1605 .addReg(FalseReg, getKillRegState(FalseIsKill))
1606 .addImm(CC);
1607
1630 unsigned ResultReg = FastEmitInst_rri(SelectOpc, RC, TrueReg, TrueIsKill,
1631 FalseReg, FalseIsKill, CC);
16081632 UpdateValueMap(I, ResultReg);
16091633 return true;
16101634 }
16831707 "Unexpected value type.");
16841708
16851709 unsigned SrcReg = getRegForValue(I->getOperand(0));
1686 if (SrcReg == 0)
1687 return false;
1710 if (!SrcReg)
1711 return false;
1712 bool SrcIsKill = hasTrivialKill(I->getOperand(0));
16881713
16891714 EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType(), true);
16901715
16921717 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
16931718 SrcReg =
16941719 EmitIntExt(SrcVT.getSimpleVT(), SrcReg, MVT::i32, /*isZExt*/ !Signed);
1695 if (SrcReg == 0)
1696 return false;
1697 }
1698
1699 MRI.constrainRegClass(SrcReg, SrcVT == MVT::i64 ? &AArch64::GPR64RegClass
1700 : &AArch64::GPR32RegClass);
1720 if (!SrcReg)
1721 return false;
1722 SrcIsKill = true;
1723 }
17011724
17021725 unsigned Opc;
17031726 if (SrcVT == MVT::i64) {
17121735 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
17131736 }
17141737
1715 unsigned ResultReg = createResultReg(TLI.getRegClassFor(DestVT));
1716 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1717 .addReg(SrcReg);
1738 unsigned ResultReg = FastEmitInst_r(Opc, TLI.getRegClassFor(DestVT), SrcReg,
1739 SrcIsKill);
17181740 UpdateValueMap(I, ResultReg);
17191741 return true;
17201742 }
17891811 for (auto const &Arg : F->args()) {
17901812 MVT VT = TLI.getSimpleValueType(Arg.getType());
17911813 unsigned SrcReg;
1814 const TargetRegisterClass *RC = nullptr;
17921815 switch (VT.SimpleTy) {
17931816 default: llvm_unreachable("Unexpected value type.");
17941817 case MVT::i1:
17951818 case MVT::i8:
17961819 case MVT::i16: VT = MVT::i32; // fall-through
1797 case MVT::i32: SrcReg = Registers[0][GPRIdx++]; break;
1798 case MVT::i64: SrcReg = Registers[1][GPRIdx++]; break;
1799 case MVT::f16: SrcReg = Registers[2][FPRIdx++]; break;
1800 case MVT::f32: SrcReg = Registers[3][FPRIdx++]; break;
1801 case MVT::f64: SrcReg = Registers[4][FPRIdx++]; break;
1820 case MVT::i32:
1821 SrcReg = Registers[0][GPRIdx++]; RC = &AArch64::GPR32RegClass; break;
1822 case MVT::i64:
1823 SrcReg = Registers[1][GPRIdx++]; RC = &AArch64::GPR64RegClass; break;
1824 case MVT::f16:
1825 SrcReg = Registers[2][FPRIdx++]; RC = &AArch64::FPR16RegClass; break;
1826 case MVT::f32:
1827 SrcReg = Registers[3][FPRIdx++]; RC = &AArch64::FPR32RegClass; break;
1828 case MVT::f64:
1829 SrcReg = Registers[4][FPRIdx++]; RC = &AArch64::FPR64RegClass; break;
18021830 }
18031831
18041832 // Skip unused arguments.
18071835 continue;
18081836 }
18091837
1810 const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
18111838 unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
18121839 // FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
18131840 // Without this, EmitLiveInCopies may eliminate the livein if its only
18151842 unsigned ResultReg = createResultReg(RC);
18161843 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
18171844 TII.get(TargetOpcode::COPY), ResultReg)
1818 .addReg(DstReg, getKillRegState(true));
1845 .addReg(DstReg, getKillRegState(true));
18191846 UpdateValueMap(&Arg, ResultReg);
18201847 }
18211848 return true;
19361963 unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT));
19371964 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
19381965 TII.get(TargetOpcode::COPY), ResultReg)
1939 .addReg(RVLocs[0].getLocReg());
1966 .addReg(RVLocs[0].getLocReg());
19401967 CLI.InRegs.push_back(RVLocs[0].getLocReg());
19411968
19421969 CLI.ResultReg = ResultReg;
21912218 static_cast(
21922219 TM.getSubtargetImpl()->getRegisterInfo());
21932220 unsigned FramePtr = RegInfo->getFrameRegister(*(FuncInfo.MF));
2194 unsigned SrcReg = FramePtr;
2195
2221 unsigned SrcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
2222 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
2223 TII.get(TargetOpcode::COPY), SrcReg).addReg(FramePtr);
21962224 // Recursively load frame address
21972225 // ldr x0, [fp]
21982226 // ldr x0, [x0]
22012229 unsigned DestReg;
22022230 unsigned Depth = cast(II->getOperand(0))->getZExtValue();
22032231 while (Depth--) {
2204 DestReg = createResultReg(&AArch64::GPR64RegClass);
2205 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
2206 TII.get(AArch64::LDRXui), DestReg)
2207 .addReg(SrcReg).addImm(0);
2232 DestReg = FastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
2233 SrcReg, /*IsKill=*/true, 0);
2234 assert(DestReg && "Unexpected LDR instruction emission failure.");
22082235 SrcReg = DestReg;
22092236 }
22102237
22972324 const Function *Callee = II->getCalledFunction();
22982325 auto *Ty = cast(Callee->getReturnType());
22992326 Type *RetTy = Ty->getTypeAtIndex(0U);
2300 Type *CondTy = Ty->getTypeAtIndex(1);
23012327
23022328 MVT VT;
23032329 if (!isTypeLegal(RetTy, VT))
23932419 TII.get(TargetOpcode::COPY), ResultReg1).addReg(MulReg);
23942420 }
23952421
2396 ResultReg2 = FuncInfo.CreateRegs(CondTy);
2422 ResultReg2 = FastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
2423 AArch64::WZR, /*IsKill=*/true, AArch64::WZR,
2424 /*IsKill=*/true, getInvertedCondCode(CC));
23972425 assert((ResultReg1 + 1) == ResultReg2 &&
23982426 "Nonconsecutive result registers.");
2399 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr),
2400 ResultReg2)
2401 .addReg(AArch64::WZR, getKillRegState(true))
2402 .addReg(AArch64::WZR, getKillRegState(true))
2403 .addImm(getInvertedCondCode(CC));
2404
24052427 UpdateValueMap(II, ResultReg1, 2);
24062428 return true;
24072429 }
25852607 // FIXME: We're SExt i1 to i64.
25862608 return 0;
25872609 }
2588 unsigned ResultReg = createResultReg(&AArch64::GPR32RegClass);
2589 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::SBFMWri),
2590 ResultReg)
2591 .addReg(SrcReg)
2592 .addImm(0)
2593 .addImm(0);
2594 return ResultReg;
2610 return FastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
2611 /*TODO:IsKill=*/false, 0, 0);
25952612 }
25962613 }
25972614
26092626 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR; break;
26102627 }
26112628
2612 // Create the base instruction, then add the operands.
2613 unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
2614 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
2615 .addReg(Op0, getKillRegState(Op0IsKill))
2616 .addReg(Op1, getKillRegState(Op1IsKill))
2617 .addReg(ZReg, getKillRegState(true));
2618
2619 return ResultReg;
2629 const TargetRegisterClass *RC =
2630 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
2631 return FastEmitInst_rrr(Opc, RC, Op0, Op0IsKill, Op1, Op1IsKill,
2632 /*IsKill=*/ZReg, true);
26202633 }
26212634
26222635 unsigned AArch64FastISel::Emit_SMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
26242637 if (RetVT != MVT::i64)
26252638 return 0;
26262639
2627 // Create the base instruction, then add the operands.
2628 unsigned ResultReg = createResultReg(&AArch64::GPR64RegClass);
2629 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::SMADDLrrr),
2630 ResultReg)
2631 .addReg(Op0, getKillRegState(Op0IsKill))
2632 .addReg(Op1, getKillRegState(Op1IsKill))
2633 .addReg(AArch64::XZR, getKillRegState(true));
2634
2635 return ResultReg;
2640 return FastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
2641 Op0, Op0IsKill, Op1, Op1IsKill,
2642 AArch64::XZR, /*IsKill=*/true);
26362643 }
26372644
26382645 unsigned AArch64FastISel::Emit_UMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
26402647 if (RetVT != MVT::i64)
26412648 return 0;
26422649
2643 // Create the base instruction, then add the operands.
2644 unsigned ResultReg = createResultReg(&AArch64::GPR64RegClass);
2645 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::UMADDLrrr),
2646 ResultReg)
2647 .addReg(Op0, getKillRegState(Op0IsKill))
2648 .addReg(Op1, getKillRegState(Op1IsKill))
2649 .addReg(AArch64::XZR, getKillRegState(true));
2650
2651 return ResultReg;
2650 return FastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
2651 Op0, Op0IsKill, Op1, Op1IsKill,
2652 AArch64::XZR, /*IsKill=*/true);
26522653 }
26532654
26542655 unsigned AArch64FastISel::Emit_LSL_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
26662667 Opc = AArch64::UBFMXri; ImmR = -Shift % 64; ImmS = 63 - Shift; break;
26672668 }
26682669
2669 RetVT.SimpleTy = std::max(MVT::i32, RetVT.SimpleTy);
2670 return FastEmitInst_rii(Opc, TLI.getRegClassFor(RetVT), Op0, Op0IsKill, ImmR,
2671 ImmS);
2670 const TargetRegisterClass *RC =
2671 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
2672 return FastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
26722673 }
26732674
26742675 unsigned AArch64FastISel::Emit_LSR_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
26822683 case MVT::i64: Opc = AArch64::UBFMXri; ImmS = 63; break;
26832684 }
26842685
2685 RetVT.SimpleTy = std::max(MVT::i32, RetVT.SimpleTy);
2686 return FastEmitInst_rii(Opc, TLI.getRegClassFor(RetVT), Op0, Op0IsKill, Shift,
2687 ImmS);
2686 const TargetRegisterClass *RC =
2687 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
2688 return FastEmitInst_rii(Opc, RC, Op0, Op0IsKill, Shift, ImmS);
26882689 }
26892690
26902691 unsigned AArch64FastISel::Emit_ASR_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
26982699 case MVT::i64: Opc = AArch64::SBFMXri; ImmS = 63; break;
26992700 }
27002701
2701 RetVT.SimpleTy = std::max(MVT::i32, RetVT.SimpleTy);
2702 return FastEmitInst_rii(Opc, TLI.getRegClassFor(RetVT), Op0, Op0IsKill, Shift,
2703 ImmS);
2702 const TargetRegisterClass *RC =
2703 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
2704 return FastEmitInst_rii(Opc, RC, Op0, Op0IsKill, Shift, ImmS);
27042705 }
27052706
27062707 unsigned AArch64FastISel::EmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
27592760 SrcReg = Src64;
27602761 }
27612762
2762 unsigned ResultReg = createResultReg(TLI.getRegClassFor(DestVT));
2763 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
2764 .addReg(SrcReg)
2765 .addImm(0)
2766 .addImm(Imm);
2767
2768 return ResultReg;
2763 const TargetRegisterClass *RC =
2764 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
2765 return FastEmitInst_rii(Opc, RC, SrcReg, /*TODO:IsKill=*/false, 0, Imm);
27692766 }
27702767
27712768 bool AArch64FastISel::SelectIntExt(const Instruction *I) {
28422839 unsigned Src0Reg = getRegForValue(I->getOperand(0));
28432840 if (!Src0Reg)
28442841 return false;
2842 bool Src0IsKill = hasTrivialKill(I->getOperand(0));
28452843
28462844 unsigned Src1Reg = getRegForValue(I->getOperand(1));
28472845 if (!Src1Reg)
28482846 return false;
2849
2850 unsigned QuotReg = createResultReg(TLI.getRegClassFor(DestVT));
2851 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(DivOpc), QuotReg)
2852 .addReg(Src0Reg)
2853 .addReg(Src1Reg);
2847 bool Src1IsKill = hasTrivialKill(I->getOperand(1));
2848
2849 const TargetRegisterClass *RC =
2850 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
2851 unsigned QuotReg = FastEmitInst_rr(DivOpc, RC, Src0Reg, /*IsKill=*/false,
2852 Src1Reg, /*IsKill=*/false);
2853 assert(QuotReg && "Unexpected DIV instruction emission failure.");
28542854 // The remainder is computed as numerator - (quotient * denominator) using the
28552855 // MSUB instruction.
2856 unsigned ResultReg = createResultReg(TLI.getRegClassFor(DestVT));
2857 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(MSubOpc), ResultReg)
2858 .addReg(QuotReg)
2859 .addReg(Src1Reg)
2860 .addReg(Src0Reg);
2856 unsigned ResultReg = FastEmitInst_rrr(MSubOpc, RC, QuotReg, /*IsKill=*/true,
2857 Src1Reg, Src1IsKill, Src0Reg,
2858 Src0IsKill);
28612859 UpdateValueMap(I, ResultReg);
28622860 return true;
28632861 }
29472945 else
29482946 return false;
29492947
2948 const TargetRegisterClass *RC = nullptr;
2949 switch (RetVT.SimpleTy) {
2950 default: llvm_unreachable("Unexpected value type.");
2951 case MVT::i32: RC = &AArch64::GPR32RegClass; break;
2952 case MVT::i64: RC = &AArch64::GPR64RegClass; break;
2953 case MVT::f32: RC = &AArch64::FPR32RegClass; break;
2954 case MVT::f64: RC = &AArch64::FPR64RegClass; break;
2955 }
29502956 unsigned Op0Reg = getRegForValue(I->getOperand(0));
29512957 if (!Op0Reg)
29522958 return false;
29532959 bool Op0IsKill = hasTrivialKill(I->getOperand(0));
2954 unsigned ResultReg = FastEmitInst_r(Opc, TLI.getRegClassFor(RetVT),
2955 Op0Reg, Op0IsKill);
2960 unsigned ResultReg = FastEmitInst_r(Opc, RC, Op0Reg, Op0IsKill);
29562961
29572962 if (!ResultReg)
29582963 return false;
None ; RUN: llc -march=arm64 -O0 < %s | FileCheck %s
1 ; RUN: llc -march=arm64 -O3 < %s | FileCheck %s
0 ; RUN: llc -march=arm64 -O0 -verify-machineinstrs < %s | FileCheck %s
1 ; RUN: llc -march=arm64 -O3 -verify-machineinstrs < %s | FileCheck %s
22
33 @.str = private unnamed_addr constant [9 x i8] c"%lf %lu\0A\00", align 1
44 @.str1 = private unnamed_addr constant [8 x i8] c"%lf %u\0A\00", align 1
None ; RUN: llc < %s -O0 -march=arm64 -aarch64-neon-syntax=apple | FileCheck %s
0 ; RUN: llc -O0 -march=arm64 -aarch64-neon-syntax=apple -verify-machineinstrs < %s | FileCheck %s
11
22 ; The following 2 test cases test shufflevector with beginning UNDEF mask.
33 define <8 x i16> @test_vext_undef_traverse(<8 x i16> %in) {
None ; RUN: llc < %s -march=arm64 -mcpu=cyclone -enable-misched=false | FileCheck %s
1 ; RUN: llc < %s -O0 | FileCheck -check-prefix=FAST %s
0 ; RUN: llc -mtriple=arm64-apple-darwin -mcpu=cyclone -enable-misched=false < %s | FileCheck %s
1 ; RUN: llc -O0 -mtriple=arm64-apple-darwin < %s | FileCheck --check-prefix=FAST %s
22 ; REQUIRES: asserts
3 target triple = "arm64-apple-darwin"
43
54 ; rdar://9932559
65 define i64 @i8i16callee(i64 %a1, i64 %a2, i64 %a3, i8 signext %a4, i16 signext %a5, i64 %a6, i64 %a7, i64 %a8, i8 signext %b1, i16 signext %b2, i8 signext %b3, i8 signext %b4) nounwind readnone noinline {
None ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
11
22 @sortlist = common global [5001 x i32] zeroinitializer, align 16
33 @sortlist2 = common global [5001 x i64] zeroinitializer, align 16
0 ; This test should cause the TargetMaterializeAlloca to be invoked
1 ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
1 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
22
33 %struct.S1Ty = type { i64 }
44 %struct.S2Ty = type { %struct.S1Ty, %struct.S1Ty }
None ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin -mcpu=cyclone | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -mtriple=arm64-apple-darwin -mcpu=cyclone -verify-machineinstrs < %s | FileCheck %s
11
22 define void @branch1() nounwind uwtable ssp {
33 %x = alloca i32, align 4
None ; RUN: llc -O0 -fast-isel-abort -fast-isel-abort-args -code-model=small -mtriple=arm64-apple-darwin < %s | FileCheck %s
1 ; RUN: llc -O0 -fast-isel-abort -fast-isel-abort-args -code-model=large -mtriple=arm64-apple-darwin < %s | FileCheck %s --check-prefix=LARGE
2 ; RUN: llc -O0 -fast-isel-abort -fast-isel-abort-args -code-model=small -mtriple=aarch64_be-linux-gnu < %s | FileCheck %s --check-prefix=CHECK-BE
0 ; RUN: llc -O0 -fast-isel-abort -fast-isel-abort-args -code-model=small -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
1 ; RUN: llc -O0 -fast-isel-abort -fast-isel-abort-args -code-model=large -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s --check-prefix=LARGE
2 ; RUN: llc -O0 -fast-isel-abort -fast-isel-abort-args -code-model=small -verify-machineinstrs -mtriple=aarch64_be-linux-gnu < %s | FileCheck %s --check-prefix=CHECK-BE
33
44 define void @call0() nounwind {
55 entry:
None ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin -mcpu=cyclone | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin -mcpu=cyclone < %s | FileCheck %s
11
22 ;; Test various conversions.
33 define zeroext i32 @trunc_(i8 zeroext %a, i16 zeroext %b, i32 %c, i64 %d) nounwind ssp {
None ; RUN: llc < %s -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
11
22 define zeroext i1 @fcmp_float1(float %a) nounwind ssp {
33 entry:
None ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
11
22 ; Test load/store of global value from global offset table.
33 @seed = common global i64 0, align 8
None ; RUN: llc -O0 -fast-isel-abort -mtriple=arm64-apple-darwin < %s | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
11
22 define i32 @icmp_eq_imm(i32 %a) nounwind ssp {
33 entry:
None ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
11
22 @fn.table = internal global [2 x i8*] [i8* blockaddress(@fn, %ZERO), i8* blockaddress(@fn, %ONE)], align 8
33
44 define i32 @fn(i32 %target) nounwind {
55 entry:
6 ; CHECK: @fn
6 ; CHECK-LABEL: fn
77 %retval = alloca i32, align 4
88 %target.addr = alloca i32, align 4
99 store i32 %target, i32* %target.addr, align 4
2828 ret i32 %2
2929
3030 indirectgoto: ; preds = %entry
31 ; CHECK: ldr x0, [sp]
32 ; CHECK: br x0
31 ; CHECK: ldr [[REG:x[0-9]+]], [sp]
32 ; CHECK-NEXT: br [[REG]]
3333 %indirect.goto.dest = phi i8* [ %1, %entry ]
3434 indirectbr i8* %indirect.goto.dest, [label %ZERO, label %ONE]
3535 }
None ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=arm64-apple-ios | FileCheck %s --check-prefix=ARM64
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -relocation-model=dynamic-no-pic -mtriple=arm64-apple-ios < %s | FileCheck %s --check-prefix=ARM64
11
22 @message = global [80 x i8] c"The LLVM Compiler Infrastructure\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", align 16
33 @temp = common global [80 x i8] zeroinitializer, align 16
None ; RUN: llc -mtriple=arm64-apple-ios -O0 %s -o - | FileCheck %s
0 ; RUN: llc -O0 -verify-machineinstrs -mtriple=aarch64-apple-ios < %s | FileCheck %s
11
22 ; Fast-isel can't do vector conversions yet, but it was emitting some highly
33 ; suspect UCVTFUWDri MachineInstrs.
None ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
11 ; RUN: llc %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin -print-machineinstrs=expand-isel-pseudos -o /dev/null 2> %t
22 ; RUN: FileCheck %s < %t --check-prefix=CHECK-SSA
33 ; REQUIRES: asserts
None ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
11
22 ;; Test returns.
33 define void @t0() nounwind ssp {
None ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -mtriple=arm64-apple-darwin -verify-machineinstrs < %s | FileCheck %s
11
22 define i32 @t1(i32 %c) nounwind readnone {
33 entry:
None ; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s
1 ; RUN: llc -mtriple=aarch64-unknown-unknown -fast-isel -fast-isel-abort < %s | FileCheck %s
0 ; RUN: llc -mtriple=aarch64-unknown-unknown -verify-machineinstrs < %s | FileCheck %s
1 ; RUN: llc -mtriple=aarch64-unknown-unknown -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s
22
33 define void @store_i8(i8* %a) {
44 ; CHECK-LABEL: store_i8
None ; RUN: llc < %s -O0 -fast-isel-abort -mtriple=arm64-apple-darwin | FileCheck %s
0 ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
11
22 define void @t0(i32 %a) nounwind {
33 entry:
None ; RUN: llc -march=arm64 -aarch64-atomic-cfg-tidy=0 < %s | FileCheck %s
1 ; RUN: llc -march=arm64 -aarch64-atomic-cfg-tidy=0 -fast-isel -fast-isel-abort < %s | FileCheck %s
0 ; RUN: llc -march=arm64 -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck %s
1 ; RUN: llc -march=arm64 -aarch64-atomic-cfg-tidy=0 -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s
22
33 ;
44 ; Get the actual value of the overflow bit.
None ; RUN: llc -mtriple=aarch64-apple-darwin < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG
1 ; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
0 ; RUN: llc -mtriple=aarch64-apple-darwin -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG
1 ; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
22
33 ; Load / Store Base Register only
44 define zeroext i1 @load_breg_i1(i1* %a) {
None ; RUN: llc -mtriple=arm64-apple-darwin -aarch64-atomic-cfg-tidy=0 < %s | FileCheck %s
1 ; RUN: llc -mtriple=arm64-apple-darwin -aarch64-atomic-cfg-tidy=0 -fast-isel -fast-isel-abort < %s | FileCheck %s
0 ; RUN: llc -mtriple=arm64-apple-darwin -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck %s
1 ; RUN: llc -mtriple=arm64-apple-darwin -aarch64-atomic-cfg-tidy=0 -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s
22
33 ; Test if the BBs are reordred according to their branch weights.
44 define i64 @branch_weights_test(i64 %a, i64 %b) {
None ; RUN: llc -fast-isel -fast-isel-abort < %s | FileCheck %s
0 ; RUN: llc -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s
11 target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
22 target triple = "aarch64-linux-gnu"
33
None ; RUN: llc -fast-isel -fast-isel-abort -mtriple=aarch64 -o - %s | FileCheck %s
0 ; RUN: llc -fast-isel -fast-isel-abort -verify-machineinstrs -mtriple=aarch64 < %s | FileCheck %s
11
22 @var8 = global i8 0
33 @var16 = global i16 0
66
77 define void @test_mul8(i8 %lhs, i8 %rhs) {
88 ; CHECK-LABEL: test_mul8:
9 ; CHECK: mul w0, w0, w1
9 ; CHECK: mul {{w[0-9]+}}, w0, w1
1010 ; %lhs = load i8* @var8
1111 ; %rhs = load i8* @var8
1212 %prod = mul i8 %lhs, %rhs
1616
1717 define void @test_mul16(i16 %lhs, i16 %rhs) {
1818 ; CHECK-LABEL: test_mul16:
19 ; CHECK: mul w0, w0, w1
19 ; CHECK: mul {{w[0-9]+}}, w0, w1
2020 %prod = mul i16 %lhs, %rhs
2121 store i16 %prod, i16* @var16
2222 ret void
2424
2525 define void @test_mul32(i32 %lhs, i32 %rhs) {
2626 ; CHECK-LABEL: test_mul32:
27 ; CHECK: mul w0, w0, w1
27 ; CHECK: mul {{w[0-9]+}}, w0, w1
2828 %prod = mul i32 %lhs, %rhs
2929 store i32 %prod, i32* @var32
3030 ret void
3232
3333 define void @test_mul64(i64 %lhs, i64 %rhs) {
3434 ; CHECK-LABEL: test_mul64:
35 ; CHECK: mul x0, x0, x1
35 ; CHECK: mul {{x[0-9]+}}, x0, x1
3636 %prod = mul i64 %lhs, %rhs
3737 store i64 %prod, i64* @var64
3838 ret void
None ; RUN: llc -fast-isel -fast-isel-abort -mtriple=arm64-apple-darwin < %s | FileCheck %s
0 ; RUN: llc -fast-isel -fast-isel-abort -mtriple=arm64-apple-darwin -verify-machineinstrs < %s | FileCheck %s
11
22 ; CHECK-LABEL: lsl_i8
33 ; CHECK: ubfiz {{w[0-9]*}}, {{w[0-9]*}}, #4, #4
None ; RUN: llc -mtriple=arm64-apple-darwin < %s | FileCheck %s
1 ; RUN: llc -mtriple=arm64-apple-darwin -fast-isel -fast-isel-abort < %s | FileCheck %s
0 ; RUN: llc -mtriple=arm64-apple-darwin -verify-machineinstrs < %s | FileCheck %s
1 ; RUN: llc -mtriple=arm64-apple-darwin -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s
22
33 define float @test_sqrt_f32(float %a) {
44 ; CHECK-LABEL: test_sqrt_f32
None ; RUN: llc -mtriple=arm64-apple-ios7.0 < %s | FileCheck %s
1 ; RUN: llc -mtriple=arm64-apple-ios7.0 -fast-isel -fast-isel-abort < %s | FileCheck %s
0 ; RUN: llc -mtriple=aarch64-apple-darwin -verify-machineinstrs < %s | FileCheck %s
1 ; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s
22
33 define i8* @test_frameaddress0() nounwind {
44 entry: