[llvm] r186681 - [SystemZ] Use SLLK, SRLK and SRAK for codegen

Richard Sandiford rsandifo at linux.vnet.ibm.com
Fri Jul 19 09:12:08 PDT 2013


Author: rsandifo
Date: Fri Jul 19 11:12:08 2013
New Revision: 186681

URL: http://llvm.org/viewvc/llvm-project?rev=186681&view=rev
Log:
[SystemZ] Use SLLK, SRLK and SRAK for codegen

This patch uses the instructions added in r186680 for codegen.

Added:
    llvm/trunk/test/CodeGen/SystemZ/shift-09.ll
Modified:
    llvm/trunk/lib/Target/SystemZ/SystemZInstrFormats.td
    llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp
    llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h

Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrFormats.td?rev=186681&r1=186680&r2=186681&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrFormats.td (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrFormats.td Fri Jul 19 11:12:08 2013
@@ -34,6 +34,12 @@ class InstSystemZ<int size, dag outs, da
   string OpKey = "";
   string OpType = "none";
 
+  // Many distinct-operands instructions have older 2-operand equivalents.
+  // NumOpsKey uniquely identifies one of these 2-operand and 3-operand pairs,
+  // with NumOpsValue being "2" or "3" as appropriate.
+  string NumOpsKey = "";
+  string NumOpsValue = "none";
+
   // True if this instruction is a simple D(X,B) load of a register
   // (with no sign or zero extension).
   bit SimpleBDXLoad = 0;
@@ -86,6 +92,7 @@ def getDisp20Opcode : InstrMapping {
   let ValueCols = [["20"]];
 }
 
+// Return the memory form of a register instruction.
 def getMemOpcode : InstrMapping {
   let FilterClass = "InstSystemZ";
   let RowFields = ["OpKey"];
@@ -94,6 +101,15 @@ def getMemOpcode : InstrMapping {
   let ValueCols = [["mem"]];
 }
 
+// Return the 3-operand form of a 2-operand instruction.
+def getThreeOperandOpcode : InstrMapping {
+  let FilterClass = "InstSystemZ";
+  let RowFields = ["NumOpsKey"];
+  let ColFields = ["NumOpsValue"];
+  let KeyCol = ["2"];
+  let ValueCols = [["3"]];
+}
+
 //===----------------------------------------------------------------------===//
 // Instruction formats
 //===----------------------------------------------------------------------===//
@@ -833,9 +849,13 @@ class ShiftRSY<string mnemonic, bits<16>
 
 multiclass ShiftRSAndK<string mnemonic, bits<8> opcode1, bits<16> opcode2,
                        SDPatternOperator operator, RegisterOperand cls> {
-  def K  : ShiftRSY<mnemonic##"k", opcode2, null_frag, cls>,
-           Requires<[FeatureDistinctOps]>;
-  def "" : ShiftRS<mnemonic, opcode1, operator, cls>;
+  let NumOpsKey = mnemonic in {
+    let NumOpsValue = "3" in
+      def K  : ShiftRSY<mnemonic##"k", opcode2, null_frag, cls>,
+               Requires<[FeatureDistinctOps]>;
+    let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in
+      def "" : ShiftRS<mnemonic, opcode1, operator, cls>;
+  }
 }
 
 class CompareRR<string mnemonic, bits<8> opcode, SDPatternOperator operator,

Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp?rev=186681&r1=186680&r2=186681&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp Fri Jul 19 11:12:08 2013
@@ -12,9 +12,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "SystemZInstrInfo.h"
+#include "SystemZTargetMachine.h"
 #include "SystemZInstrBuilder.h"
+#include "llvm/CodeGen/LiveVariables.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetMachine.h"
 
 #define GET_INSTRINFO_CTOR
 #define GET_INSTRMAP_INFO
@@ -24,7 +25,7 @@ using namespace llvm;
 
 SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm)
   : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP),
-    RI(tm) {
+    RI(tm), TM(tm) {
 }
 
 // MI is a 128-bit load or store.  Split it into two 64-bit loads or stores,
@@ -352,6 +353,48 @@ static bool isSimpleBD12Move(const Machi
 }
 
 MachineInstr *
+SystemZInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
+                                        MachineBasicBlock::iterator &MBBI,
+                                        LiveVariables *LV) const {
+  MachineInstr *MI = MBBI;
+  MachineBasicBlock *MBB = MI->getParent();
+
+  unsigned Opcode = MI->getOpcode();
+  unsigned NumOps = MI->getNumOperands();
+
+  // Try to convert something like SLL into SLLK, if supported.
+  // We prefer to keep the two-operand form where possible both
+  // because it tends to be shorter and because some instructions
+  // have memory forms that can be used during spilling.
+  if (TM.getSubtargetImpl()->hasDistinctOps()) {
+    int ThreeOperandOpcode = SystemZ::getThreeOperandOpcode(Opcode);
+    if (ThreeOperandOpcode >= 0) {
+      unsigned DestReg = MI->getOperand(0).getReg();
+      MachineOperand &Src = MI->getOperand(1);
+      MachineInstrBuilder MIB = BuildMI(*MBB, MBBI, MI->getDebugLoc(),
+                                        get(ThreeOperandOpcode), DestReg);
+      // Keep the kill state, but drop the tied flag.
+      MIB.addReg(Src.getReg(), getKillRegState(Src.isKill()));
+      // Keep the remaining operands as-is.
+      for (unsigned I = 2; I < NumOps; ++I)
+        MIB.addOperand(MI->getOperand(I));
+      MachineInstr *NewMI = MIB;
+
+      // Transfer killing information to the new instruction.
+      if (LV) {
+        for (unsigned I = 1; I < NumOps; ++I) {
+          MachineOperand &Op = MI->getOperand(I);
+          if (Op.isReg() && Op.isKill())
+            LV->replaceKillInstruction(Op.getReg(), MI, NewMI);
+        }
+      }
+      return MIB;
+    }
+  }
+  return 0;
+}
+
+MachineInstr *
 SystemZInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
                                         MachineInstr *MI,
                                         const SmallVectorImpl<unsigned> &Ops,

Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h?rev=186681&r1=186680&r2=186681&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h Fri Jul 19 11:12:08 2013
@@ -79,6 +79,7 @@ namespace SystemZII {
 
 class SystemZInstrInfo : public SystemZGenInstrInfo {
   const SystemZRegisterInfo RI;
+  SystemZTargetMachine &TM;
 
   void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const;
   void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const;
@@ -120,6 +121,10 @@ public:
                          const TargetRegisterClass *RC,
                          const TargetRegisterInfo *TRI) const LLVM_OVERRIDE;
   virtual MachineInstr *
+    convertToThreeAddress(MachineFunction::iterator &MFI,
+                          MachineBasicBlock::iterator &MBBI,
+                          LiveVariables *LV) const;
+  virtual MachineInstr *
     foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
                           const SmallVectorImpl<unsigned> &Ops,
                           int FrameIndex) const;

Added: llvm/trunk/test/CodeGen/SystemZ/shift-09.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/shift-09.ll?rev=186681&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/shift-09.ll (added)
+++ llvm/trunk/test/CodeGen/SystemZ/shift-09.ll Fri Jul 19 11:12:08 2013
@@ -0,0 +1,63 @@
+; Test three-operand shifts.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s
+
+; Check that we use SLLK over SLL where useful.
+define i32 @f1(i32 %a, i32 %b, i32 %amt) {
+; CHECK-LABEL: f1:
+; CHECK: sllk %r2, %r3, 15(%r4)
+; CHECK: br %r14
+  %add = add i32 %amt, 15
+  %shift = shl i32 %b, %add
+  ret i32 %shift
+}
+
+; Check that we use SLL over SLLK where possible.
+define i32 @f2(i32 %a, i32 %amt) {
+; CHECK-LABEL: f2:
+; CHECK: sll %r2, 15(%r3)
+; CHECK: br %r14
+  %add = add i32 %amt, 15
+  %shift = shl i32 %a, %add
+  ret i32 %shift
+}
+
+; Check that we use SRLK over SRL where useful.
+define i32 @f3(i32 %a, i32 %b, i32 %amt) {
+; CHECK-LABEL: f3:
+; CHECK: srlk %r2, %r3, 15(%r4)
+; CHECK: br %r14
+  %add = add i32 %amt, 15
+  %shift = lshr i32 %b, %add
+  ret i32 %shift
+}
+
+; Check that we use SRL over SRLK where possible.
+define i32 @f4(i32 %a, i32 %amt) {
+; CHECK-LABEL: f4:
+; CHECK: srl %r2, 15(%r3)
+; CHECK: br %r14
+  %add = add i32 %amt, 15
+  %shift = lshr i32 %a, %add
+  ret i32 %shift
+}
+
+; Check that we use SRAK over SRA where useful.
+define i32 @f5(i32 %a, i32 %b, i32 %amt) {
+; CHECK-LABEL: f5:
+; CHECK: srak %r2, %r3, 15(%r4)
+; CHECK: br %r14
+  %add = add i32 %amt, 15
+  %shift = ashr i32 %b, %add
+  ret i32 %shift
+}
+
+; Check that we use SRA over SRAK where possible.
+define i32 @f6(i32 %a, i32 %amt) {
+; CHECK-LABEL: f6:
+; CHECK: sra %r2, 15(%r3)
+; CHECK: br %r14
+  %add = add i32 %amt, 15
+  %shift = ashr i32 %a, %add
+  ret i32 %shift
+}





More information about the llvm-commits mailing list