[llvm] r217007 - [FastISel][AArch64] Add target-dependent instruction selection for Add/Sub.

Juergen Ributzka juergen at apple.com
Tue Sep 2 18:38:36 PDT 2014


Author: ributzka
Date: Tue Sep  2 20:38:36 2014
New Revision: 217007

URL: http://llvm.org/viewvc/llvm-project?rev=217007&view=rev
Log:
[FastISel][AArch64] Add target-dependent instruction selection for Add/Sub.

There is already target-dependent instruction selection support for Adds/Subs to
support compares and the intrinsics with overflow check. This takes advantage of
the existing infrastructure to also support Add/Sub, which allows the folding of
immediates, sign-/zero-extends, and shifts.

This fixes rdar://problem/18207316.

Modified:
    llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
    llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll

Modified: llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp?rev=217007&r1=217006&r2=217007&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp Tue Sep  2 20:38:36 2014
@@ -113,6 +113,7 @@ class AArch64FastISel : public FastISel
 
 private:
   // Selection routines.
+  bool selectAddSub(const Instruction *I);
   bool SelectLoad(const Instruction *I);
   bool SelectStore(const Instruction *I);
   bool SelectBranch(const Instruction *I);
@@ -149,32 +150,25 @@ private:
                          const Value *Cond);
 
   // Emit helper routines.
-  unsigned emitAddsSubs(bool UseAdds, MVT RetVT, const Value *LHS,
-                        const Value *RHS, bool IsZExt = false,
-                        bool WantResult = true);
-  unsigned emitAddsSubs_rr(bool UseAdds, MVT RetVT, unsigned LHSReg,
-                           bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
-                           bool WantResult = true);
-  unsigned emitAddsSubs_ri(bool UseAdds, MVT RetVT, unsigned LHSReg,
-                           bool LHSIsKill, uint64_t Imm,
-                           bool WantResult = true);
+  unsigned emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
+                      const Value *RHS, bool SetFlags = false,
+                      bool WantResult = true,  bool IsZExt = false);
+  unsigned emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
+                         bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
+                         bool SetFlags = false, bool WantResult = true);
+  unsigned emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
+                         bool LHSIsKill, uint64_t Imm, bool SetFlags = false,
+                         bool WantResult = true);
   unsigned emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
                          bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
                          AArch64_AM::ShiftExtendType ShiftType,
-                         uint64_t ShiftImm, bool WantResult = true);
-  unsigned emitAddsSubs_rs(bool UseAdds, MVT RetVT, unsigned LHSReg,
-                           bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
-                           AArch64_AM::ShiftExtendType ShiftType,
-                           uint64_t ShiftImm, bool WantResult = true);
+                         uint64_t ShiftImm, bool SetFlags = false,
+                         bool WantResult = true);
   unsigned emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
                          bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
                           AArch64_AM::ShiftExtendType ExtType,
-                          uint64_t ShiftImm, bool WantResult = true);
-
-  unsigned emitAddsSubs_rx(bool UseAdds, MVT RetVT, unsigned LHSReg,
-                           bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
-                           AArch64_AM::ShiftExtendType ExtType,
-                           uint64_t ShiftImm, bool WantResult = true);
+                          uint64_t ShiftImm, bool SetFlags = false,
+                         bool WantResult = true);
 
   // Emit functions.
   bool emitCmp(const Value *LHS, const Value *RHS, bool IsZExt);
@@ -187,10 +181,12 @@ private:
                  MachineMemOperand *MMO = nullptr);
   unsigned EmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
   unsigned Emiti1Ext(unsigned SrcReg, MVT DestVT, bool isZExt);
-  unsigned emitAdds(MVT RetVT, const Value *LHS, const Value *RHS,
-                    bool IsZExt = false, bool WantResult = true);
-  unsigned emitSubs(MVT RetVT, const Value *LHS, const Value *RHS,
-                    bool IsZExt = false, bool WantResult = true);
+  unsigned emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
+                   bool SetFlags = false, bool WantResult = true,
+                   bool IsZExt = false);
+  unsigned emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
+                   bool SetFlags = false, bool WantResult = true,
+                   bool IsZExt = false);
   unsigned emitSubs_rr(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
                        unsigned RHSReg, bool RHSIsKill, bool WantResult = true);
   unsigned emitSubs_rs(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
@@ -855,9 +851,9 @@ void AArch64FastISel::AddLoadStoreOperan
     MIB.addMemOperand(MMO);
 }
 
-unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT,
-                                       const Value *LHS, const Value *RHS,
-                                       bool IsZExt, bool WantResult) {
+unsigned AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
+                                     const Value *RHS, bool SetFlags,
+                                     bool WantResult,  bool IsZExt) {
   AArch64_AM::ShiftExtendType ExtendType = AArch64_AM::InvalidShiftExtend;
   bool NeedExtend = false;
   switch (RetVT.SimpleTy) {
@@ -882,11 +878,11 @@ unsigned AArch64FastISel::emitAddsSubs(b
   RetVT.SimpleTy = std::max(RetVT.SimpleTy, MVT::i32);
 
   // Canonicalize immediates to the RHS first.
-  if (UseAdds && isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
+  if (UseAdd && isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
     std::swap(LHS, RHS);
 
   // Canonicalize shift immediate to the RHS.
-  if (UseAdds && isValueAvailable(LHS))
+  if (UseAdd && isValueAvailable(LHS))
     if (const auto *SI = dyn_cast<BinaryOperator>(LHS))
       if (isa<ConstantInt>(SI->getOperand(1)))
         if (SI->getOpcode() == Instruction::Shl  ||
@@ -906,11 +902,11 @@ unsigned AArch64FastISel::emitAddsSubs(b
   if (const auto *C = dyn_cast<ConstantInt>(RHS)) {
     uint64_t Imm = IsZExt ? C->getZExtValue() : C->getSExtValue();
     if (C->isNegative())
-      ResultReg =
-          emitAddsSubs_ri(!UseAdds, RetVT, LHSReg, LHSIsKill, -Imm, WantResult);
+      ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, LHSIsKill, -Imm,
+                                SetFlags, WantResult);
     else
-      ResultReg =
-          emitAddsSubs_ri(UseAdds, RetVT, LHSReg, LHSIsKill, Imm, WantResult);
+      ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, LHSIsKill, Imm, SetFlags,
+                                WantResult);
   }
   if (ResultReg)
     return ResultReg;
@@ -924,16 +920,16 @@ unsigned AArch64FastISel::emitAddsSubs(b
           if (!RHSReg)
             return 0;
           bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
-          return emitAddsSubs_rx(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg,
-                                 RHSIsKill, ExtendType, C->getZExtValue(),
-                                 WantResult);
+          return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
+                               RHSIsKill, ExtendType, C->getZExtValue(),
+                               SetFlags, WantResult);
         }
     unsigned RHSReg = getRegForValue(RHS);
     if (!RHSReg)
       return 0;
     bool RHSIsKill = hasTrivialKill(RHS);
-    return emitAddsSubs_rx(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
-                           ExtendType, 0, WantResult);
+    return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
+                         ExtendType, 0, SetFlags, WantResult);
   }
 
   // Check if the shift can be folded into the instruction.
@@ -953,8 +949,9 @@ unsigned AArch64FastISel::emitAddsSubs(b
           if (!RHSReg)
             return 0;
           bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
-          return emitAddsSubs_rs(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg,
-                                 RHSIsKill, ShiftType, ShiftVal, WantResult);
+          return emitAddSub_rs(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
+                               RHSIsKill, ShiftType, ShiftVal, SetFlags,
+                               WantResult);
         }
       }
     }
@@ -967,31 +964,34 @@ unsigned AArch64FastISel::emitAddsSubs(b
   if (NeedExtend)
     RHSReg = EmitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
 
-  return emitAddsSubs_rr(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
-                         WantResult);
+  return emitAddSub_rr(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
+                       SetFlags, WantResult);
 }
 
-unsigned AArch64FastISel::emitAddsSubs_rr(bool UseAdds, MVT RetVT,
-                                          unsigned LHSReg, bool LHSIsKill,
-                                          unsigned RHSReg, bool RHSIsKill,
-                                          bool WantResult) {
+unsigned AArch64FastISel::emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
+                                        bool LHSIsKill, unsigned RHSReg,
+                                        bool RHSIsKill, bool SetFlags,
+                                        bool WantResult) {
   assert(LHSReg && RHSReg && "Invalid register number.");
 
   if (RetVT != MVT::i32 && RetVT != MVT::i64)
     return 0;
 
-  static const unsigned OpcTable[2][2] = {
-    { AArch64::ADDSWrr, AArch64::ADDSXrr },
-    { AArch64::SUBSWrr, AArch64::SUBSXrr }
+  static const unsigned OpcTable[2][2][2] = {
+    { { AArch64::SUBWrr,  AArch64::SUBXrr  },
+      { AArch64::ADDWrr,  AArch64::ADDXrr  }  },
+    { { AArch64::SUBSWrr, AArch64::SUBSXrr },
+      { AArch64::ADDSWrr, AArch64::ADDSXrr }  }
   };
-  unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
+  bool Is64Bit = RetVT == MVT::i64;
+  unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
+  const TargetRegisterClass *RC =
+      Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
   unsigned ResultReg;
-  if (WantResult) {
-    const TargetRegisterClass *RC =
-        (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+  if (WantResult)
     ResultReg = createResultReg(RC);
-  } else
-    ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
+  else
+    ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
 
   const MCInstrDesc &II = TII.get(Opc);
   LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
@@ -999,13 +999,12 @@ unsigned AArch64FastISel::emitAddsSubs_r
   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
       .addReg(LHSReg, getKillRegState(LHSIsKill))
       .addReg(RHSReg, getKillRegState(RHSIsKill));
-
   return ResultReg;
 }
 
-unsigned AArch64FastISel::emitAddsSubs_ri(bool UseAdds, MVT RetVT,
-                                          unsigned LHSReg, bool LHSIsKill,
-                                          uint64_t Imm, bool WantResult) {
+unsigned AArch64FastISel::emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
+                                        bool LHSIsKill, uint64_t Imm,
+                                        bool SetFlags, bool WantResult) {
   assert(LHSReg && "Invalid register number.");
 
   if (RetVT != MVT::i32 && RetVT != MVT::i64)
@@ -1020,18 +1019,24 @@ unsigned AArch64FastISel::emitAddsSubs_r
   } else
     return 0;
 
-  static const unsigned OpcTable[2][2] = {
-    { AArch64::ADDSWri, AArch64::ADDSXri },
-    { AArch64::SUBSWri, AArch64::SUBSXri }
+  static const unsigned OpcTable[2][2][2] = {
+    { { AArch64::SUBWri,  AArch64::SUBXri  },
+      { AArch64::ADDWri,  AArch64::ADDXri  }  },
+    { { AArch64::SUBSWri, AArch64::SUBSXri },
+      { AArch64::ADDSWri, AArch64::ADDSXri }  }
   };
-  unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
+  bool Is64Bit = RetVT == MVT::i64;
+  unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
+  const TargetRegisterClass *RC;
+  if (SetFlags)
+    RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+  else
+    RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
   unsigned ResultReg;
-  if (WantResult) {
-    const TargetRegisterClass *RC =
-        (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+  if (WantResult)
     ResultReg = createResultReg(RC);
-  } else
-    ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
+  else
+    ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
 
   const MCInstrDesc &II = TII.get(Opc);
   LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
@@ -1039,66 +1044,35 @@ unsigned AArch64FastISel::emitAddsSubs_r
       .addReg(LHSReg, getKillRegState(LHSIsKill))
       .addImm(Imm)
       .addImm(getShifterImm(AArch64_AM::LSL, ShiftImm));
-
   return ResultReg;
 }
 
-unsigned AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT,
-                                        unsigned LHSReg, bool LHSIsKill,
-                                        unsigned RHSReg, bool RHSIsKill,
+unsigned AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
+                                        bool LHSIsKill, unsigned RHSReg,
+                                        bool RHSIsKill,
                                         AArch64_AM::ShiftExtendType ShiftType,
-                                        uint64_t ShiftImm, bool WantResult) {
-  assert(LHSReg && RHSReg && "Invalid register number.");
-
-  if (RetVT != MVT::i32 && RetVT != MVT::i64)
-    return 0;
-
-  static const unsigned OpcTable[2][2] = {
-    { AArch64::ADDWrs, AArch64::ADDXrs },
-    { AArch64::SUBWrs, AArch64::SUBXrs }
-  };
-  unsigned Opc = OpcTable[!UseAdd][(RetVT == MVT::i64)];
-  unsigned ResultReg;
-  if (WantResult) {
-    const TargetRegisterClass *RC =
-        (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
-    ResultReg = createResultReg(RC);
-  } else
-    ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
-
-  const MCInstrDesc &II = TII.get(Opc);
-  LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
-  RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
-  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
-      .addReg(LHSReg, getKillRegState(LHSIsKill))
-      .addReg(RHSReg, getKillRegState(RHSIsKill))
-      .addImm(getShifterImm(ShiftType, ShiftImm));
-  
-  return ResultReg;
-}
-
-unsigned AArch64FastISel::emitAddsSubs_rs(bool UseAdds, MVT RetVT,
-                                          unsigned LHSReg, bool LHSIsKill,
-                                          unsigned RHSReg, bool RHSIsKill,
-                                          AArch64_AM::ShiftExtendType ShiftType,
-                                          uint64_t ShiftImm, bool WantResult) {
+                                        uint64_t ShiftImm, bool SetFlags,
+                                        bool WantResult) {
   assert(LHSReg && RHSReg && "Invalid register number.");
 
   if (RetVT != MVT::i32 && RetVT != MVT::i64)
     return 0;
 
-  static const unsigned OpcTable[2][2] = {
-    { AArch64::ADDSWrs, AArch64::ADDSXrs },
-    { AArch64::SUBSWrs, AArch64::SUBSXrs }
+  static const unsigned OpcTable[2][2][2] = {
+    { { AArch64::SUBWrs,  AArch64::SUBXrs  },
+      { AArch64::ADDWrs,  AArch64::ADDXrs  }  },
+    { { AArch64::SUBSWrs, AArch64::SUBSXrs },
+      { AArch64::ADDSWrs, AArch64::ADDSXrs }  }
   };
-  unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
+  bool Is64Bit = RetVT == MVT::i64;
+  unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
+  const TargetRegisterClass *RC =
+      Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
   unsigned ResultReg;
-  if (WantResult) {
-    const TargetRegisterClass *RC =
-        (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+  if (WantResult)
     ResultReg = createResultReg(RC);
-  } else
-    ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
+  else
+    ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
 
   const MCInstrDesc &II = TII.get(Opc);
   LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
@@ -1107,66 +1081,38 @@ unsigned AArch64FastISel::emitAddsSubs_r
       .addReg(LHSReg, getKillRegState(LHSIsKill))
       .addReg(RHSReg, getKillRegState(RHSIsKill))
       .addImm(getShifterImm(ShiftType, ShiftImm));
-
   return ResultReg;
 }
 
-unsigned AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT,
-                                        unsigned LHSReg, bool LHSIsKill,
-                                        unsigned RHSReg, bool RHSIsKill,
+unsigned AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
+                                        bool LHSIsKill, unsigned RHSReg,
+                                        bool RHSIsKill,
                                         AArch64_AM::ShiftExtendType ExtType,
-                                        uint64_t ShiftImm, bool WantResult) {
+                                        uint64_t ShiftImm, bool SetFlags,
+                                        bool WantResult) {
   assert(LHSReg && RHSReg && "Invalid register number.");
 
   if (RetVT != MVT::i32 && RetVT != MVT::i64)
     return 0;
 
-  static const unsigned OpcTable[2][2] = {
-    { AArch64::ADDWrx, AArch64::ADDXrx },
-    { AArch64::SUBWrx, AArch64::SUBXrx }
+  static const unsigned OpcTable[2][2][2] = {
+    { { AArch64::SUBWrx,  AArch64::SUBXrx  },
+      { AArch64::ADDWrx,  AArch64::ADDXrx  }  },
+    { { AArch64::SUBSWrx, AArch64::SUBSXrx },
+      { AArch64::ADDSWrx, AArch64::ADDSXrx }  }
   };
-  unsigned Opc = OpcTable[!UseAdd][(RetVT == MVT::i64)];
-  unsigned ResultReg;
-  if (WantResult) {
-    const TargetRegisterClass *RC =
-        (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
-    ResultReg = createResultReg(RC);
-  } else
-    ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
-
-  const MCInstrDesc &II = TII.get(Opc);
-  LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
-  RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
-  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
-      .addReg(LHSReg, getKillRegState(LHSIsKill))
-      .addReg(RHSReg, getKillRegState(RHSIsKill))
-      .addImm(getArithExtendImm(ExtType, ShiftImm));
-
-  return ResultReg;
-}
-
-unsigned AArch64FastISel::emitAddsSubs_rx(bool UseAdds, MVT RetVT,
-                                          unsigned LHSReg, bool LHSIsKill,
-                                          unsigned RHSReg, bool RHSIsKill,
-                                          AArch64_AM::ShiftExtendType ExtType,
-                                          uint64_t ShiftImm, bool WantResult) {
-  assert(LHSReg && RHSReg && "Invalid register number.");
-
-  if (RetVT != MVT::i32 && RetVT != MVT::i64)
-    return 0;
-
-  static const unsigned OpcTable[2][2] = {
-    { AArch64::ADDSWrx, AArch64::ADDSXrx },
-    { AArch64::SUBSWrx, AArch64::SUBSXrx }
-  };
-  unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
+  bool Is64Bit = RetVT == MVT::i64;
+  unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
+  const TargetRegisterClass *RC = nullptr;
+  if (SetFlags)
+    RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+  else
+    RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
   unsigned ResultReg;
-  if (WantResult) {
-    const TargetRegisterClass *RC =
-        (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+  if (WantResult)
     ResultReg = createResultReg(RC);
-  } else
-    ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
+  else
+    ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
 
   const MCInstrDesc &II = TII.get(Opc);
   LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
@@ -1175,7 +1121,6 @@ unsigned AArch64FastISel::emitAddsSubs_r
       .addReg(LHSReg, getKillRegState(LHSIsKill))
       .addReg(RHSReg, getKillRegState(RHSIsKill))
       .addImm(getArithExtendImm(ExtType, ShiftImm));
-
   return ResultReg;
 }
 
@@ -1203,13 +1148,14 @@ bool AArch64FastISel::emitCmp(const Valu
 
 bool AArch64FastISel::emitICmp(MVT RetVT, const Value *LHS, const Value *RHS,
                                bool IsZExt) {
-  return emitSubs(RetVT, LHS, RHS, IsZExt, /*WantResult=*/false) != 0;
+  return emitSub(RetVT, LHS, RHS, /*SetFlags=*/true, /*WantResult=*/false,
+                 IsZExt) != 0;
 }
 
 bool AArch64FastISel::emitICmp_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
                                   uint64_t Imm) {
-  return emitAddsSubs_ri(false, RetVT, LHSReg, LHSIsKill, Imm,
-                         /*WantResult=*/false) != 0;
+  return emitAddSub_ri(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, Imm,
+                       /*SetFlags=*/true, /*WantResult=*/false) != 0;
 }
 
 bool AArch64FastISel::emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS) {
@@ -1247,23 +1193,23 @@ bool AArch64FastISel::emitFCmp(MVT RetVT
   return true;
 }
 
-unsigned AArch64FastISel::emitAdds(MVT RetVT, const Value *LHS,
-                                   const Value *RHS, bool IsZExt,
-                                   bool WantResult) {
-  return emitAddsSubs(true, RetVT, LHS, RHS, IsZExt, WantResult);
+unsigned AArch64FastISel::emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
+                                  bool SetFlags, bool WantResult, bool IsZExt) {
+  return emitAddSub(/*UseAdd=*/true, RetVT, LHS, RHS, SetFlags, WantResult,
+                    IsZExt);
 }
 
-unsigned AArch64FastISel::emitSubs(MVT RetVT, const Value *LHS,
-                                   const Value *RHS, bool IsZExt,
-                                   bool WantResult) {
-  return emitAddsSubs(false, RetVT, LHS, RHS, IsZExt, WantResult);
+unsigned AArch64FastISel::emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
+                                  bool SetFlags, bool WantResult, bool IsZExt) {
+  return emitAddSub(/*UseAdd=*/false, RetVT, LHS, RHS, SetFlags, WantResult,
+                    IsZExt);
 }
 
 unsigned AArch64FastISel::emitSubs_rr(MVT RetVT, unsigned LHSReg,
                                       bool LHSIsKill, unsigned RHSReg,
                                       bool RHSIsKill, bool WantResult) {
-  return emitAddsSubs_rr(false, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
-                         WantResult);
+  return emitAddSub_rr(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, RHSReg,
+                       RHSIsKill, /*SetFlags=*/true, WantResult);
 }
 
 unsigned AArch64FastISel::emitSubs_rs(MVT RetVT, unsigned LHSReg,
@@ -1271,8 +1217,9 @@ unsigned AArch64FastISel::emitSubs_rs(MV
                                       bool RHSIsKill,
                                       AArch64_AM::ShiftExtendType ShiftType,
                                       uint64_t ShiftImm, bool WantResult) {
-  return emitAddsSubs_rs(false, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
-                         ShiftType, ShiftImm, WantResult);
+  return emitAddSub_rs(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, RHSReg,
+                       RHSIsKill, ShiftType, ShiftImm, /*SetFlags=*/true,
+                       WantResult);
 }
 
 // FIXME: This should be eventually generated automatically by tblgen.
@@ -1376,6 +1323,24 @@ bool AArch64FastISel::EmitLoad(MVT VT, u
   return true;
 }
 
+bool AArch64FastISel::selectAddSub(const Instruction *I) {
+  MVT VT;
+  if (!isTypeSupported(I->getType(), VT))
+    return false;
+
+  unsigned ResultReg;
+  if (I->getOpcode() == Instruction::Add)
+    ResultReg = emitAdd(VT, I->getOperand(0), I->getOperand(1));
+  else if (I->getOpcode() == Instruction::Sub)
+    ResultReg = emitSub(VT, I->getOperand(0), I->getOperand(1));
+  else
+    llvm_unreachable("Unexpected instruction.");
+
+  assert(ResultReg && "Couldn't select Add/Sub instruction.");
+  UpdateValueMap(I, ResultReg);
+  return true;
+}
+
 bool AArch64FastISel::SelectLoad(const Instruction *I) {
   MVT VT;
   // Verify we have a legal type before going any further.  Currently, we handle
@@ -2512,13 +2477,21 @@ bool AArch64FastISel::FastLowerIntrinsic
     switch (II->getIntrinsicID()) {
     default: llvm_unreachable("Unexpected intrinsic!");
     case Intrinsic::sadd_with_overflow:
-      ResultReg1 = emitAdds(VT, LHS, RHS); CC = AArch64CC::VS; break;
+      ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
+      CC = AArch64CC::VS;
+      break;
     case Intrinsic::uadd_with_overflow:
-      ResultReg1 = emitAdds(VT, LHS, RHS); CC = AArch64CC::HS; break;
+      ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
+      CC = AArch64CC::HS;
+      break;
     case Intrinsic::ssub_with_overflow:
-      ResultReg1 = emitSubs(VT, LHS, RHS); CC = AArch64CC::VS; break;
+      ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
+      CC = AArch64CC::VS;
+      break;
     case Intrinsic::usub_with_overflow:
-      ResultReg1 = emitSubs(VT, LHS, RHS); CC = AArch64CC::LO; break;
+      ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
+      CC = AArch64CC::LO;
+      break;
     case Intrinsic::smul_with_overflow: {
       CC = AArch64CC::NE;
       unsigned LHSReg = getRegForValue(LHS);
@@ -3442,11 +3415,15 @@ bool AArch64FastISel::TargetSelectInstru
   default:
     return false;
   case Instruction::Add:
-    return SelectBinaryOp(I, ISD::ADD);
+    if (!selectAddSub(I))
+      return SelectBinaryOp(I, ISD::ADD);
+    return true;
+  case Instruction::Sub:
+    if (!selectAddSub(I))
+      return SelectBinaryOp(I, ISD::SUB);
+    return true;
   case Instruction::FAdd:
     return SelectBinaryOp(I, ISD::FADD);
-  case Instruction::Sub:
-    return SelectBinaryOp(I, ISD::SUB);
   case Instruction::FSub:
     // FNeg is currently represented in LLVM IR as a special case of FSub.
     if (BinaryOperator::isFNeg(I))

Modified: llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll?rev=217007&r1=217006&r2=217007&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll Tue Sep  2 20:38:36 2014
@@ -6,9 +6,9 @@
 define void @Initrand() nounwind {
 entry:
 ; CHECK: @Initrand
-; CHECK: adrp x[[REG:[0-9]+]], _seed at GOTPAGE
-; CHECK: ldr x[[REG2:[0-9]+]], [x[[REG]], _seed at GOTPAGEOFF]
-; CHECK: str x{{[0-9]+}}, [x[[REG2]]]
+; CHECK: adrp [[REG:x[0-9]+]], _seed at GOTPAGE
+; CHECK: ldr  [[REG2:x[0-9]+]], {{\[}}[[REG]], _seed at GOTPAGEOFF{{\]}}
+; CHECK: str  {{x[0-9]+}}, {{\[}}[[REG2]]{{\]}}
   store i64 74755, i64* @seed, align 8
   ret void
 }
@@ -16,17 +16,17 @@ entry:
 define i32 @Rand() nounwind {
 entry:
 ; CHECK: @Rand
-; CHECK: adrp x[[REG:[0-9]+]], _seed at GOTPAGE
-; CHECK: ldr x[[REG2:[0-9]+]], [x[[REG]], _seed at GOTPAGEOFF]
-; CHECK: movz x[[REG3:[0-9]+]], #0x51d
-; CHECK: ldr x[[REG4:[0-9]+]], [x[[REG2]]]
-; CHECK: mul x[[REG5:[0-9]+]], x[[REG4]], x[[REG3]]
-; CHECK: movz x[[REG6:[0-9]+]], #0x3619
-; CHECK: add x[[REG7:[0-9]+]], x[[REG5]], x[[REG6]]
-; CHECK: orr x[[REG8:[0-9]+]], xzr, #0xffff
-; CHECK: and x[[REG9:[0-9]+]], x[[REG7]], x[[REG8]]
-; CHECK: str x[[REG9]], [x[[REG]]]
-; CHECK: ldr x{{[0-9]+}}, [x[[REG]]]
+; CHECK: adrp [[REG1:x[0-9]+]], _seed at GOTPAGE
+; CHECK: ldr  [[REG2:x[0-9]+]], {{\[}}[[REG1]], _seed at GOTPAGEOFF{{\]}}
+; CHECK: movz [[REG3:x[0-9]+]], #0x3619
+; CHECK: movz [[REG4:x[0-9]+]], #0x51d
+; CHECK: ldr  [[REG5:x[0-9]+]], {{\[}}[[REG2]]{{\]}}
+; CHECK: mul  [[REG6:x[0-9]+]], [[REG5]], [[REG4]]
+; CHECK: add  [[REG7:x[0-9]+]], [[REG6]], [[REG3]]
+; CHECK: orr  [[REG8:x[0-9]+]], xzr, #0xffff
+; CHECK: and  [[REG9:x[0-9]+]], [[REG7]], [[REG8]]
+; CHECK: str  [[REG9]], {{\[}}[[REG1]]{{\]}}
+; CHECK: ldr  {{x[0-9]+}}, {{\[}}[[REG1]]{{\]}}
   %0 = load i64* @seed, align 8
   %mul = mul nsw i64 %0, 1309
   %add = add nsw i64 %mul, 13849





More information about the llvm-commits mailing list