[SystemZ] Implement isLegalAddressingMode()
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Wed, 31 Jul 2013 12:58:26 +0000 (12:58 +0000)
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Wed, 31 Jul 2013 12:58:26 +0000 (12:58 +0000)
The loop optimizers were assuming that scales > 1 were OK.  I think this
is actually a bug in TargetLoweringBase::isLegalAddressingMode(),
since it seems to be trying to reject anything that isn't r+i or r+r,
but it has no default case for scales other than 0, 1 or 2.  Implementing
the hook for z means that z can no longer test any change there though.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187497 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SystemZ/SystemZISelLowering.cpp
lib/Target/SystemZ/SystemZISelLowering.h
test/CodeGen/SystemZ/loop-01.ll [new file with mode: 0644]

index 34697fed80bcf5ff1d5cc931367c485c9ebc86dc..6a34fec7ee16968509e6d765553a61a761f89463 100644 (file)
@@ -290,6 +290,21 @@ bool SystemZTargetLowering::allowsUnalignedMemoryAccesses(EVT VT,
   return true;
 }
   
+bool SystemZTargetLowering::isLegalAddressingMode(const AddrMode &AM,
+                                                  Type *Ty) const {
+  // Punt on globals for now, although they can be used in limited
+  // RELATIVE LONG cases.
+  if (AM.BaseGV)
+    return false;
+
+  // Require a 20-bit signed offset.
+  if (!isInt<20>(AM.BaseOffs))
+    return false;
+
+  // Indexing is OK but no scale factor can be applied.
+  return AM.Scale == 0 || AM.Scale == 1;
+}
+
 //===----------------------------------------------------------------------===//
 // Inline asm support
 //===----------------------------------------------------------------------===//
index ce876a981bd88ad61aae56ef23c3328cb2fe509d..c0dbe493c0f5abf34c81164f1f48fa1f6989f1c4 100644 (file)
@@ -126,12 +126,15 @@ public:
   virtual MVT getScalarShiftAmountTy(EVT LHSTy) const LLVM_OVERRIDE {
     return MVT::i32;
   }
-  virtual EVT getSetCCResultType(LLVMContext &, EVT) const {
+  virtual EVT getSetCCResultType(LLVMContext &, EVT) const LLVM_OVERRIDE {
     return MVT::i32;
   }
   virtual bool isFMAFasterThanFMulAndFAdd(EVT VT) const LLVM_OVERRIDE;
-  virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const;
-  virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const;
+  virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const LLVM_OVERRIDE;
+  virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const
+     LLVM_OVERRIDE;
+  virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const
+    LLVM_OVERRIDE;
   virtual const char *getTargetNodeName(unsigned Opcode) const LLVM_OVERRIDE;
   virtual std::pair<unsigned, const TargetRegisterClass *>
     getRegForInlineAsmConstraint(const std::string &Constraint,
diff --git a/test/CodeGen/SystemZ/loop-01.ll b/test/CodeGen/SystemZ/loop-01.ll
new file mode 100644 (file)
index 0000000..025a34e
--- /dev/null
@@ -0,0 +1,25 @@
+; Test loop tuning.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
+
+; Test that strength reduction is applied to addresses with a scale factor,
+; but that indexed addressing can still be used.
+define void @f1(i32 *%dest, i32 %a) {
+; CHECK-LABEL: f1
+; CHECK-NOT: sllg
+; CHECK: st %r3, 0({{%r[1-5],%r[1-5]}})
+; CHECK: br %r14
+entry:
+  br label %loop
+
+loop:
+  %index = phi i64 [ 0, %entry ], [ %next, %loop ]
+  %ptr = getelementptr i32 *%dest, i64 %index
+  store i32 %a, i32 *%ptr
+  %next = add i64 %index, 1
+  %cmp = icmp ne i64 %next, 100
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  ret void
+}