[ARM64-BE] Fix fast-isel, and add appropriate RUN lines to appropriate tests.
[oota-llvm.git] / lib / Target / ARM64 / ARM64FastISel.cpp
index 0fce1cc64e3bfad93f73b60a61cd959171f1ac5a..78cde1c22c99ec1801382b7cc1c93df4db8c91b6 100644 (file)
@@ -197,6 +197,9 @@ unsigned ARM64FastISel::TargetMaterializeAlloca(const AllocaInst *AI) {
 }
 
 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);
 
@@ -418,7 +421,11 @@ bool ARM64FastISel::isTypeLegal(Type *Ty, MVT &VT) {
     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);
 }
@@ -570,7 +577,8 @@ bool ARM64FastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address Addr,
 
   // 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)
@@ -658,7 +666,8 @@ bool ARM64FastISel::EmitStore(MVT VT, unsigned SrcReg, Address Addr,
 
   // 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)
@@ -781,7 +790,8 @@ bool ARM64FastISel::SelectBranch(const Instruction *I) {
         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)
@@ -1023,7 +1033,9 @@ bool ARM64FastISel::SelectSelect(const Instruction *I) {
   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)
@@ -1107,6 +1119,8 @@ bool ARM64FastISel::SelectFPToInt(const Instruction *I, bool Signed) {
     return false;
 
   EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType(), true);
+  if (SrcVT == MVT::f128)
+    return false;
 
   unsigned Opc;
   if (SrcVT == MVT::f64) {
@@ -1132,6 +1146,8 @@ bool ARM64FastISel::SelectIntToFP(const Instruction *I, bool Signed) {
   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)
@@ -1577,7 +1593,14 @@ bool ARM64FastISel::SelectRet(const Instruction *I) {
     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) {
@@ -1656,8 +1679,9 @@ bool ARM64FastISel::SelectTrunc(const Instruction *I) {
     // 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)
@@ -1678,7 +1702,8 @@ unsigned ARM64FastISel::Emiti1Ext(unsigned SrcReg, MVT DestVT, bool isZExt) {
     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)