[LoongArch] Implement TargetLowering::isLegalAddressingMode() hook
authorgonglingqin <gonglingqin@loongson.cn>
Thu, 2 Feb 2023 06:00:04 +0000 (14:00 +0800)
committergonglingqin <gonglingqin@loongson.cn>
Thu, 2 Feb 2023 06:01:44 +0000 (14:01 +0800)
Use the exact addressing mode information instead of the default to
make better use of offsets in instructions.

Differential Revision: https://reviews.llvm.org/D142874

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
llvm/lib/Target/LoongArch/LoongArchISelLowering.h
llvm/test/CodeGen/LoongArch/ldptr.ll
llvm/test/CodeGen/LoongArch/stptr.ll

index 0eb0d18..d4684a5 100644 (file)
@@ -3142,3 +3142,48 @@ bool LoongArchTargetLowering::decomposeMulByConstant(LLVMContext &Context,
 
   return false;
 }
+
+bool LoongArchTargetLowering::isLegalAddressingMode(const DataLayout &DL,
+                                                    const AddrMode &AM,
+                                                    Type *Ty, unsigned AS,
+                                                    Instruction *I) const {
+  // LoongArch has four basic addressing modes:
+  //  1. reg
+  //  2. reg + 12-bit signed offset
+  //  3. reg + 14-bit signed offset left-shifted by 2
+  //  4. reg1 + reg2
+  // TODO: Add more checks after support vector extension.
+
+  // No global is ever allowed as a base.
+  if (AM.BaseGV)
+    return false;
+
+  // Require a 12 or 14 bit signed offset.
+  if (!isInt<12>(AM.BaseOffs) || !isShiftedInt<14, 2>(AM.BaseOffs))
+    return false;
+
+  switch (AM.Scale) {
+  case 0:
+    // "i" is not allowed.
+    if (!AM.HasBaseReg)
+      return false;
+    // Otherwise we have "r+i".
+    break;
+  case 1:
+    // "r+r+i" is not allowed.
+    if (AM.HasBaseReg && AM.BaseOffs != 0)
+      return false;
+    // Otherwise we have "r+r" or "r+i".
+    break;
+  case 2:
+    // "2*r+r" or "2*r+i" is not allowed.
+    if (AM.HasBaseReg || AM.BaseOffs)
+      return false;
+    // Otherwise we have "r+r".
+    break;
+  default:
+    return false;
+  }
+
+  return true;
+}
index 43a30f0..bb4341e 100644 (file)
@@ -183,6 +183,10 @@ public:
 
   bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override;
 
+  bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
+                             unsigned AS,
+                             Instruction *I = nullptr) const override;
+
 private:
   /// Target-specific function used to lower LoongArch calling conventions.
   typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI,
index 8125416..bab449b 100644 (file)
@@ -81,12 +81,10 @@ entry:
 define i64 @ldptr_d(ptr %p) nounwind {
 ; LA32-LABEL: ldptr_d:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    ori $a1, $zero, 2052
+; LA32-NEXT:    ori $a1, $zero, 2048
 ; LA32-NEXT:    add.w $a1, $a0, $a1
-; LA32-NEXT:    ori $a2, $zero, 2048
-; LA32-NEXT:    add.w $a0, $a0, $a2
-; LA32-NEXT:    ld.w $a0, $a0, 0
-; LA32-NEXT:    ld.w $a1, $a1, 0
+; LA32-NEXT:    ld.w $a0, $a1, 0
+; LA32-NEXT:    ld.w $a1, $a1, 4
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: ldptr_d:
@@ -104,11 +102,9 @@ define i64 @ldptr_d_too_big_offset(ptr %p) nounwind {
 ; LA32-LABEL: ldptr_d_too_big_offset:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    lu12i.w $a1, 8
-; LA32-NEXT:    ori $a2, $a1, 4
-; LA32-NEXT:    add.w $a2, $a0, $a2
-; LA32-NEXT:    add.w $a0, $a0, $a1
-; LA32-NEXT:    ld.w $a0, $a0, 0
-; LA32-NEXT:    ld.w $a1, $a2, 0
+; LA32-NEXT:    add.w $a1, $a0, $a1
+; LA32-NEXT:    ld.w $a0, $a1, 0
+; LA32-NEXT:    ld.w $a1, $a1, 4
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: ldptr_d_too_big_offset:
index 5b6998b..644a931 100644 (file)
@@ -76,11 +76,9 @@ define void @stptr_d_too_small_offset(ptr %p, i64 %val) nounwind {
 define void @stptr_d(ptr %p, i64 %val) nounwind {
 ; LA32-LABEL: stptr_d:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a3, $zero, 2052
-; LA32-NEXT:    add.w $a3, $a0, $a3
-; LA32-NEXT:    st.w $a2, $a3, 0
-; LA32-NEXT:    ori $a2, $zero, 2048
-; LA32-NEXT:    add.w $a0, $a0, $a2
+; LA32-NEXT:    ori $a3, $zero, 2048
+; LA32-NEXT:    add.w $a0, $a0, $a3
+; LA32-NEXT:    st.w $a2, $a0, 4
 ; LA32-NEXT:    st.w $a1, $a0, 0
 ; LA32-NEXT:    ret
 ;
@@ -98,11 +96,9 @@ define void @stptr_d_too_big_offset(ptr %p, i64 %val) nounwind {
 ; LA32-LABEL: stptr_d_too_big_offset:
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    lu12i.w $a3, 8
-; LA32-NEXT:    add.w $a4, $a0, $a3
-; LA32-NEXT:    st.w $a1, $a4, 0
-; LA32-NEXT:    ori $a1, $a3, 4
-; LA32-NEXT:    add.w $a0, $a0, $a1
-; LA32-NEXT:    st.w $a2, $a0, 0
+; LA32-NEXT:    add.w $a0, $a0, $a3
+; LA32-NEXT:    st.w $a2, $a0, 4
+; LA32-NEXT:    st.w $a1, $a0, 0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: stptr_d_too_big_offset: