public:
// Backend specific FastISel code.
- virtual unsigned TargetMaterializeAlloca(const AllocaInst *AI);
- virtual unsigned TargetMaterializeConstant(const Constant *C);
+ unsigned TargetMaterializeAlloca(const AllocaInst *AI) override;
+ unsigned TargetMaterializeConstant(const Constant *C) override;
explicit ARM64FastISel(FunctionLoweringInfo &funcInfo,
const TargetLibraryInfo *libInfo)
Context = &funcInfo.Fn->getContext();
}
- virtual bool TargetSelectInstruction(const Instruction *I);
+ bool TargetSelectInstruction(const Instruction *I) override;
#include "ARM64GenFastISel.inc"
};
}
unsigned ARM64FastISel::ARM64MaterializeFP(const ConstantFP *CFP, MVT VT) {
+ if (VT != MVT::f32 && VT != MVT::f64)
+ return 0;
+
const APFloat Val = CFP->getValueAPF();
bool is64bit = (VT == MVT::f64);
Align = DL.getTypeAllocSize(CFP->getType());
unsigned Idx = MCP.getConstantPoolIndex(cast<Constant>(CFP), Align);
- unsigned ADRPReg = createResultReg(&ARM64::GPR64RegClass);
+ unsigned ADRPReg = createResultReg(&ARM64::GPR64commonRegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ADRP),
ADRPReg).addConstantPoolIndex(Idx, 0, ARM64II::MO_PAGE);
EVT DestEVT = TLI.getValueType(GV->getType(), true);
if (!DestEVT.isSimple())
return 0;
- MVT DestVT = DestEVT.getSimpleVT();
- unsigned ADRPReg = createResultReg(&ARM64::GPR64RegClass);
- unsigned ResultReg = createResultReg(TLI.getRegClassFor(DestVT));
+ unsigned ADRPReg = createResultReg(&ARM64::GPR64commonRegClass);
+ unsigned ResultReg;
if (OpFlags & ARM64II::MO_GOT) {
// ADRP + LDRX
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ADRP),
ADRPReg)
.addGlobalAddress(GV, 0, ARM64II::MO_GOT | ARM64II::MO_PAGE);
+
+ ResultReg = createResultReg(&ARM64::GPR64RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::LDRXui),
ResultReg)
.addReg(ADRPReg)
.addGlobalAddress(GV, 0, ARM64II::MO_GOT | ARM64II::MO_PAGEOFF |
- ARM64II::MO_NC);
+ ARM64II::MO_NC);
} else {
// ADRP + ADDX
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ADRP),
ADRPReg).addGlobalAddress(GV, 0, ARM64II::MO_PAGE);
+
+ ResultReg = createResultReg(&ARM64::GPR64spRegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ADDXri),
ResultReg)
.addReg(ADRPReg)
// Computes the address to get to an object.
bool ARM64FastISel::ComputeAddress(const Value *Obj, Address &Addr) {
- const User *U = NULL;
+ const User *U = nullptr;
unsigned Opcode = Instruction::UserOp1;
if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
// Don't walk into other basic blocks unless the object is an alloca from
return false;
VT = evt.getSimpleVT();
- // Handle all legal types, i.e. a register that will directly hold this
+ // This is a legal type, but it's not something we handle in fast-isel.
+ if (VT == MVT::f128)
+ return false;
+
+ // Handle all other legal types, i.e. a register that will directly hold this
// value.
return TLI.isTypeLegal(VT);
}
// Loading an i1 requires special handling.
if (VTIsi1) {
- unsigned ANDReg = createResultReg(&ARM64::GPR32RegClass);
+ MRI.constrainRegClass(ResultReg, &ARM64::GPR32RegClass);
+ unsigned ANDReg = createResultReg(&ARM64::GPR32spRegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ANDWri),
ANDReg)
.addReg(ResultReg)
// Storing an i1 requires special handling.
if (VTIsi1) {
- unsigned ANDReg = createResultReg(&ARM64::GPR32RegClass);
+ MRI.constrainRegClass(SrcReg, &ARM64::GPR32RegClass);
+ unsigned ANDReg = createResultReg(&ARM64::GPR32spRegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ANDWri),
ANDReg)
.addReg(SrcReg)
case CmpInst::ICMP_NE:
return ARM64CC::NE;
case CmpInst::ICMP_UGE:
- return ARM64CC::CS;
+ return ARM64CC::HS;
case CmpInst::ICMP_ULT:
- return ARM64CC::CC;
+ return ARM64CC::LO;
}
}
CondReg = FastEmitInst_extractsubreg(MVT::i32, CondReg, /*Kill=*/true,
ARM64::sub_32);
- unsigned ANDReg = createResultReg(&ARM64::GPR32RegClass);
+ MRI.constrainRegClass(CondReg, &ARM64::GPR32RegClass);
+ unsigned ANDReg = createResultReg(&ARM64::GPR32spRegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ANDWri),
ANDReg)
.addReg(CondReg)
if (FalseReg == 0)
return false;
- unsigned ANDReg = createResultReg(&ARM64::GPR32RegClass);
+
+ MRI.constrainRegClass(CondReg, &ARM64::GPR32RegClass);
+ unsigned ANDReg = createResultReg(&ARM64::GPR32spRegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ANDWri),
ANDReg)
.addReg(CondReg)
return false;
EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType(), true);
+ if (SrcVT == MVT::f128)
+ return false;
unsigned Opc;
if (SrcVT == MVT::f64) {
else
Opc = (DestVT == MVT::i32) ? ARM64::FCVTZUUWSr : ARM64::FCVTZUUXSr;
}
- unsigned ResultReg = createResultReg(TLI.getRegClassFor(DestVT));
+ unsigned ResultReg = createResultReg(
+ DestVT == MVT::i32 ? &ARM64::GPR32RegClass : &ARM64::GPR64RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
.addReg(SrcReg);
UpdateValueMap(I, ResultReg);
MVT DestVT;
if (!isTypeLegal(I->getType(), DestVT) || DestVT.isVector())
return false;
+ assert ((DestVT == MVT::f32 || DestVT == MVT::f64) &&
+ "Unexpected value type.");
unsigned SrcReg = getRegForValue(I->getOperand(0));
if (SrcReg == 0)
return false;
}
+ MRI.constrainRegClass(SrcReg, SrcVT == MVT::i64 ? &ARM64::GPR64RegClass
+ : &ARM64::GPR32RegClass);
+
unsigned Opc;
if (SrcVT == MVT::i64) {
if (Signed)
}
bool ARM64FastISel::SelectCall(const Instruction *I,
- const char *IntrMemName = 0) {
+ const char *IntrMemName = nullptr) {
const CallInst *CI = cast<CallInst>(I);
const Value *Callee = CI->getCalledValue();
EVT RVEVT = TLI.getValueType(RV->getType());
if (!RVEVT.isSimple())
return false;
+
+ // Vectors (of > 1 lane) in big endian need tricky handling.
+ if (RVEVT.isVector() && RVEVT.getVectorNumElements() > 1)
+ return false;
+
MVT RVVT = RVEVT.getSimpleVT();
+ if (RVVT == MVT::f128)
+ return false;
MVT DestVT = VA.getValVT();
// Special handling for extended integers.
if (RVVT != DestVT) {
// Issue an extract_subreg to get the lower 32-bits.
unsigned Reg32 = FastEmitInst_extractsubreg(MVT::i32, SrcReg, /*Kill=*/true,
ARM64::sub_32);
+ MRI.constrainRegClass(Reg32, &ARM64::GPR32RegClass);
// Create the AND instruction which performs the actual truncation.
- unsigned ANDReg = createResultReg(&ARM64::GPR32RegClass);
+ unsigned ANDReg = createResultReg(&ARM64::GPR32spRegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ANDWri),
ANDReg)
.addReg(Reg32)
DestVT = MVT::i32;
if (isZExt) {
- unsigned ResultReg = createResultReg(&ARM64::GPR32RegClass);
+ MRI.constrainRegClass(SrcReg, &ARM64::GPR32RegClass);
+ unsigned ResultReg = createResultReg(&ARM64::GPR32spRegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(ARM64::ANDWri),
ResultReg)
.addReg(SrcReg)
// Handle i8 and i16 as i32.
if (DestVT == MVT::i8 || DestVT == MVT::i16)
DestVT = MVT::i32;
+ else if (DestVT == MVT::i64) {
+ unsigned Src64 = MRI.createVirtualRegister(&ARM64::GPR64RegClass);
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ TII.get(ARM64::SUBREG_TO_REG), Src64)
+ .addImm(0)
+ .addReg(SrcReg)
+ .addImm(ARM64::sub_32);
+ SrcReg = Src64;
+ }
unsigned ResultReg = createResultReg(TLI.getRegClassFor(DestVT));
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(DivOpc), ResultReg)
.addReg(Src0Reg)
.addReg(Src1Reg);
- // The remainder is computed as numerator – (quotient * denominator) using the
+ // The remainder is computed as numerator - (quotient * denominator) using the
// MSUB instruction.
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(MSubOpc), ResultReg)
.addReg(ResultReg)