[SystemZ] Support RISBGN instruction on zEC12
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 31 Mar 2015 12:58:17 +0000 (12:58 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 31 Mar 2015 12:58:17 +0000 (12:58 +0000)
So far, we do not yet support any instruction specific to zEC12.
Most of the facilities added with zEC12 are indeed not very useful
to compiler code generation, but there is one exception: the
miscellaneous-extensions facility provides the RISBGN instruction,
which is a variant of RISBG that does not set the condition code.

Add support for this facility, MC support for RISBGN, and CodeGen
support for prefering RISBGN over RISBG on zEC12, unless we can
actually make use of the condition code set by RISBG.

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

lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
lib/Target/SystemZ/SystemZInstrInfo.cpp
lib/Target/SystemZ/SystemZInstrInfo.td
lib/Target/SystemZ/SystemZProcessors.td
lib/Target/SystemZ/SystemZSubtarget.cpp
lib/Target/SystemZ/SystemZSubtarget.h
test/CodeGen/SystemZ/risbg-03.ll [new file with mode: 0644]
test/MC/Disassembler/SystemZ/insns.txt
test/MC/SystemZ/insn-bad-z196.s
test/MC/SystemZ/insn-bad-zEC12.s [new file with mode: 0644]
test/MC/SystemZ/insn-good-zEC12.s [new file with mode: 0644]

index a52aa2560bc7f08f0e30d3eb587983b4e3c4aeba..1a58b531c03937762cdceac86de5502b8dd786b8 100644 (file)
@@ -898,6 +898,9 @@ SDNode *SystemZDAGToDAGISel::tryRISBGZero(SDNode *N) {
   }  
 
   unsigned Opcode = SystemZ::RISBG;
+  // Prefer RISBGN if available, since it does not clobber CC.
+  if (Subtarget->hasMiscellaneousExtensions())
+    Opcode = SystemZ::RISBGN;
   EVT OpcodeVT = MVT::i64;
   if (VT == MVT::i32 && Subtarget->hasHighWord()) {
     Opcode = SystemZ::RISBMux;
@@ -945,9 +948,13 @@ SDNode *SystemZDAGToDAGISel::tryRxSBG(SDNode *N, unsigned Opcode) {
 
   // See whether we can avoid an AND in the first operand by converting
   // ROSBG to RISBG.
-  if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[I].Mask))
+  if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[I].Mask)) {
     Opcode = SystemZ::RISBG;
-           
+    // Prefer RISBGN if available, since it does not clobber CC.
+    if (Subtarget->hasMiscellaneousExtensions())
+      Opcode = SystemZ::RISBGN;
+  }
+
   EVT VT = N->getValueType(0);
   SDValue Ops[5] = {
     convertTo(SDLoc(N), MVT::i64, Op0),
index 5128993713f57c67154904700c257caa382fc2bf..3a028594fa4294461f4112beabb06d9b3340cea5 100644 (file)
@@ -723,9 +723,12 @@ SystemZInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
     unsigned Start, End;
     if (isRxSBGMask(Imm, And.RegSize, Start, End)) {
       unsigned NewOpcode;
-      if (And.RegSize == 64)
+      if (And.RegSize == 64) {
         NewOpcode = SystemZ::RISBG;
-      else {
+        // Prefer RISBGN if available, since it does not clobber CC.
+        if (STI.hasMiscellaneousExtensions())
+          NewOpcode = SystemZ::RISBGN;
+      } else {
         NewOpcode = SystemZ::RISBMux;
         Start &= 31;
         End &= 31;
@@ -1146,17 +1149,22 @@ unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
 
 unsigned SystemZInstrInfo::getLoadAndTest(unsigned Opcode) const {
   switch (Opcode) {
-  case SystemZ::L:    return SystemZ::LT;
-  case SystemZ::LY:   return SystemZ::LT;
-  case SystemZ::LG:   return SystemZ::LTG;
-  case SystemZ::LGF:  return SystemZ::LTGF;
-  case SystemZ::LR:   return SystemZ::LTR;
-  case SystemZ::LGFR: return SystemZ::LTGFR;
-  case SystemZ::LGR:  return SystemZ::LTGR;
-  case SystemZ::LER:  return SystemZ::LTEBR;
-  case SystemZ::LDR:  return SystemZ::LTDBR;
-  case SystemZ::LXR:  return SystemZ::LTXBR;
-  default:            return 0;
+  case SystemZ::L:      return SystemZ::LT;
+  case SystemZ::LY:     return SystemZ::LT;
+  case SystemZ::LG:     return SystemZ::LTG;
+  case SystemZ::LGF:    return SystemZ::LTGF;
+  case SystemZ::LR:     return SystemZ::LTR;
+  case SystemZ::LGFR:   return SystemZ::LTGFR;
+  case SystemZ::LGR:    return SystemZ::LTGR;
+  case SystemZ::LER:    return SystemZ::LTEBR;
+  case SystemZ::LDR:    return SystemZ::LTDBR;
+  case SystemZ::LXR:    return SystemZ::LTXBR;
+  // On zEC12 we prefer to use RISBGN.  But if there is a chance to
+  // actually use the condition code, we may turn it back into RISGB.
+  // Note that RISBG is not really a "load-and-test" instruction,
+  // but sets the same condition code values, so is OK to use here.
+  case SystemZ::RISBGN: return SystemZ::RISBG;
+  default:              return 0;
   }
 }
 
index 31db301d95e3df79123b064d51a491cae923c3d8..cc95975e014f9cde256983c2ac9e1cd0a144887d 100644 (file)
@@ -1061,6 +1061,10 @@ let Defs = [CC] in {
     def RISBG : RotateSelectRIEf<"risbg", 0xEC55, GR64, GR64>;
 }
 
+// On zEC12 we have a variant of RISBG that does not set CC.
+let Predicates = [FeatureMiscellaneousExtensions] in
+  def RISBGN : RotateSelectRIEf<"risbgn", 0xEC59, GR64, GR64>;
+
 // Forms of RISBG that only affect one word of the destination register.
 // They do not set CC.
 let Predicates = [FeatureHighWord] in {
index b8bbd5677e0b0befe9622a6844c533b552661a75..0563cae637e94b7464f3f9c266210b259a4d4ce9 100644 (file)
@@ -55,6 +55,11 @@ def FeatureInterlockedAccess1 : SystemZFeature<
 >;
 def FeatureNoInterlockedAccess1 : SystemZMissingFeature<"InterlockedAccess1">;
 
+def FeatureMiscellaneousExtensions : SystemZFeature<
+  "miscellaneous-extensions", "MiscellaneousExtensions",
+  "Assume that the miscellaneous-extensions facility is installed"
+>;
+
 def : Processor<"generic", NoItineraries, []>;
 def : Processor<"z10", NoItineraries, []>;
 def : Processor<"z196", NoItineraries,
@@ -64,4 +69,5 @@ def : Processor<"z196", NoItineraries,
 def : Processor<"zEC12", NoItineraries,
                 [FeatureDistinctOps, FeatureLoadStoreOnCond, FeatureHighWord,
                  FeatureFPExtension, FeaturePopulationCount,
-                 FeatureFastSerialization, FeatureInterlockedAccess1]>;
+                 FeatureFastSerialization, FeatureInterlockedAccess1,
+                 FeatureMiscellaneousExtensions]>;
index 0999b45c9d61de2b28c6d479ef39f0c0878b5797..8b8d2edab42fce553074e38eccaf09d34fb223b0 100644 (file)
@@ -39,7 +39,7 @@ SystemZSubtarget::SystemZSubtarget(const std::string &TT,
     : SystemZGenSubtargetInfo(TT, CPU, FS), HasDistinctOps(false),
       HasLoadStoreOnCond(false), HasHighWord(false), HasFPExtension(false),
       HasPopulationCount(false), HasFastSerialization(false),
-      HasInterlockedAccess1(false),
+      HasInterlockedAccess1(false), HasMiscellaneousExtensions(false),
       TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(CPU, FS)),
       TLInfo(TM, *this), TSInfo(*TM.getDataLayout()), FrameLowering() {}
 
index b3e7a3512cd265440b9a0e56e292c8275d4ac445..d48de44ed9669bc3ac1cc4321d47c60236909cc4 100644 (file)
@@ -41,6 +41,7 @@ protected:
   bool HasPopulationCount;
   bool HasFastSerialization;
   bool HasInterlockedAccess1;
+  bool HasMiscellaneousExtensions;
 
 private:
   Triple TargetTriple;
@@ -96,6 +97,11 @@ public:
   // Return true if the target has interlocked-access facility 1.
   bool hasInterlockedAccess1() const { return HasInterlockedAccess1; }
 
+  // Return true if the target has the miscellaneous-extensions facility.
+  bool hasMiscellaneousExtensions() const {
+    return HasMiscellaneousExtensions;
+  }
+
   // Return true if GV can be accessed using LARL for reloc model RM
   // and code model CM.
   bool isPC32DBLSymbol(const GlobalValue *GV, Reloc::Model RM,
diff --git a/test/CodeGen/SystemZ/risbg-03.ll b/test/CodeGen/SystemZ/risbg-03.ll
new file mode 100644 (file)
index 0000000..c3c08ad
--- /dev/null
@@ -0,0 +1,30 @@
+; Test use of RISBG vs RISBGN on zEC12.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s
+
+; On zEC12, we generally prefer RISBGN.
+define i64 @f1(i64 %a, i64 %b) {
+; CHECK-LABEL: f1:
+; CHECK: risbgn %r2, %r3, 60, 62, 0
+; CHECK: br %r14
+  %anda = and i64 %a, -15
+  %andb = and i64 %b, 14
+  %or = or i64 %anda, %andb
+  ret i64 %or
+}
+
+; But we may fall back to RISBG if we can use the condition code.
+define i64 @f2(i64 %a, i64 %b, i32* %c) {
+; CHECK-LABEL: f2:
+; CHECK: risbg %r2, %r3, 60, 62, 0
+; CHECK-NEXT: ipm
+; CHECK: br %r14
+  %anda = and i64 %a, -15
+  %andb = and i64 %b, 14
+  %or = or i64 %anda, %andb
+  %cmp = icmp sgt i64 %or, 0
+  %conv = zext i1 %cmp to i32
+  store i32 %conv, i32* %c, align 4
+  ret i64 %or
+}
+
index df032dc53f9a9daca96be803d39e8247522f7a7e..cf130899790bf7c254470007110b3678683c98ea 100644 (file)
 # CHECK: risbg %r4, %r5, 6, 7, 8
 0xec 0x45 0x06 0x07 0x08 0x55
 
+# CHECK: risbgn %r0, %r0, 0, 0, 0
+0xec 0x00 0x00 0x00 0x00 0x59
+
+# CHECK: risbgn %r0, %r0, 0, 0, 63
+0xec 0x00 0x00 0x00 0x3f 0x59
+
+# CHECK: risbgn %r0, %r0, 0, 255, 0
+0xec 0x00 0x00 0xff 0x00 0x59
+
+# CHECK: risbgn %r0, %r0, 255, 0, 0
+0xec 0x00 0xff 0x00 0x00 0x59
+
+# CHECK: risbgn %r0, %r15, 0, 0, 0
+0xec 0x0f 0x00 0x00 0x00 0x59
+
+# CHECK: risbgn %r15, %r0, 0, 0, 0
+0xec 0xf0 0x00 0x00 0x00 0x59
+
+# CHECK: risbgn %r4, %r5, 6, 7, 8
+0xec 0x45 0x06 0x07 0x08 0x59
+
 # CHECK: risbhg %r0, %r0, 0, 0, 0
 0xec 0x00 0x00 0x00 0x00 0x5d
 
index 47dbe08b25252804f9d7620d331fea0d01cd7a87..deebe6dce2b7bb5ddefa676a29444ae407e669e6 100644 (file)
        locr    %r0,%r0,-1
        locr    %r0,%r0,16
 
+#CHECK: error: {{(instruction requires: miscellaneous-extensions)?}}
+#CHECK: risbgn %r1, %r2, 0, 0, 0
+
+       risbgn  %r1, %r2, 0, 0, 0
+
 #CHECK: error: invalid operand
 #CHECK: risbhg %r0,%r0,0,0,-1
 #CHECK: error: invalid operand
diff --git a/test/MC/SystemZ/insn-bad-zEC12.s b/test/MC/SystemZ/insn-bad-zEC12.s
new file mode 100644 (file)
index 0000000..42d41ca
--- /dev/null
@@ -0,0 +1,24 @@
+# For zEC12 only.
+# RUN: not llvm-mc -triple s390x-linux-gnu -mcpu=zEC12 < %s 2> %t
+# RUN: FileCheck < %t %s
+
+#CHECK: error: invalid operand
+#CHECK: risbgn %r0,%r0,0,0,-1
+#CHECK: error: invalid operand
+#CHECK: risbgn %r0,%r0,0,0,64
+#CHECK: error: invalid operand
+#CHECK: risbgn %r0,%r0,0,-1,0
+#CHECK: error: invalid operand
+#CHECK: risbgn %r0,%r0,0,256,0
+#CHECK: error: invalid operand
+#CHECK: risbgn %r0,%r0,-1,0,0
+#CHECK: error: invalid operand
+#CHECK: risbgn %r0,%r0,256,0,0
+
+       risbgn  %r0,%r0,0,0,-1
+       risbgn  %r0,%r0,0,0,64
+       risbgn  %r0,%r0,0,-1,0
+       risbgn  %r0,%r0,0,256,0
+       risbgn  %r0,%r0,-1,0,0
+       risbgn  %r0,%r0,256,0,0
+
diff --git a/test/MC/SystemZ/insn-good-zEC12.s b/test/MC/SystemZ/insn-good-zEC12.s
new file mode 100644 (file)
index 0000000..6f8f0ac
--- /dev/null
@@ -0,0 +1,19 @@
+# For zEC12 and above.
+# RUN: llvm-mc -triple s390x-linux-gnu -mcpu=zEC12 -show-encoding %s | FileCheck %s
+
+#CHECK: risbgn %r0, %r0, 0, 0, 0       # encoding: [0xec,0x00,0x00,0x00,0x00,0x59]
+#CHECK: risbgn %r0, %r0, 0, 0, 63      # encoding: [0xec,0x00,0x00,0x00,0x3f,0x59]
+#CHECK: risbgn %r0, %r0, 0, 255, 0     # encoding: [0xec,0x00,0x00,0xff,0x00,0x59]
+#CHECK: risbgn %r0, %r0, 255, 0, 0     # encoding: [0xec,0x00,0xff,0x00,0x00,0x59]
+#CHECK: risbgn %r0, %r15, 0, 0, 0      # encoding: [0xec,0x0f,0x00,0x00,0x00,0x59]
+#CHECK: risbgn %r15, %r0, 0, 0, 0      # encoding: [0xec,0xf0,0x00,0x00,0x00,0x59]
+#CHECK: risbgn %r4, %r5, 6, 7, 8       # encoding: [0xec,0x45,0x06,0x07,0x08,0x59]
+
+       risbgn  %r0,%r0,0,0,0
+       risbgn  %r0,%r0,0,0,63
+       risbgn  %r0,%r0,0,255,0
+       risbgn  %r0,%r0,255,0,0
+       risbgn  %r0,%r15,0,0,0
+       risbgn  %r15,%r0,0,0,0
+       risbgn  %r4,%r5,6,7,8
+