[SystemZ] Add LOC and LOCG

As with the stores, these instructions can trap when the condition is false,
so they are only used for things like (cond ? x : *ptr).

llvm-svn: 187112
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrFormats.td b/llvm/lib/Target/SystemZ/SystemZInstrFormats.td
index b92c350..8199c17 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrFormats.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrFormats.td
@@ -704,6 +704,46 @@
   let AddedComplexity = 7;
 }
 
+class CondUnaryRSY<string mnemonic, bits<16> opcode,
+                   RegisterOperand cls, bits<5> bytes,
+                   AddressingMode mode = bdaddr20only>
+  : InstRSY<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$BD2, cond4:$R3),
+            mnemonic#"$R3\t$R1, $BD2", []>,
+    Requires<[FeatureLoadStoreOnCond]> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+  let mayLoad = 1;
+  let AccessBytes = bytes;
+}
+
+// Like CondUnaryRSY, but used for the raw assembly form.  The condition-code
+// mask is the third operand rather than being part of the mnemonic.
+class AsmCondUnaryRSY<string mnemonic, bits<16> opcode,
+                      RegisterOperand cls, bits<5> bytes,
+                      AddressingMode mode = bdaddr20only>
+  : InstRSY<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$BD2, uimm8zx4:$R3),
+            mnemonic#"\t$R1, $BD2, $R3", []>,
+    Requires<[FeatureLoadStoreOnCond]> {
+  let mayLoad = 1;
+  let AccessBytes = bytes;
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+}
+
+// Like CondUnaryRSY, but with a fixed CC mask.
+class FixedCondUnaryRSY<string mnemonic, bits<16> opcode,
+                        RegisterOperand cls, bits<4> ccmask, bits<5> bytes,
+                        AddressingMode mode = bdaddr20only>
+  : InstRSY<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$BD2),
+            mnemonic#"\t$R1, $BD2", []>,
+    Requires<[FeatureLoadStoreOnCond]> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+  let R3 = ccmask;
+  let mayLoad = 1;
+  let AccessBytes = bytes;
+}
+
 class UnaryRX<string mnemonic, bits<8> opcode, SDPatternOperator operator,
               RegisterOperand cls, bits<5> bytes,
               AddressingMode mode = bdxaddr12only>
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
index bda34df..46cd764 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -112,6 +112,8 @@
     def JG : InstRIL<0xC04, (outs), (ins brtarget32:$I2),
                      "jg"##name##"\t$I2", []>;
   }
+  def LOC   : FixedCondUnaryRSY<"loc"##name,   0xEBF2, GR32, ccmask, 4>;
+  def LOCG  : FixedCondUnaryRSY<"locg"##name,  0xEBE2, GR64, ccmask, 8>;
   def STOC  : FixedCondStoreRSY<"stoc"##name,  0xEBF3, GR32, ccmask, 4>;
   def STOCG : FixedCondStoreRSY<"stocg"##name, 0xEBE3, GR64, ccmask, 8>;
 }
@@ -259,6 +261,18 @@
   def LGRL : UnaryRILPC<"lgrl", 0xC48, aligned_load, GR64>;
 }
 
+// Load on condition.
+let isCodeGenOnly = 1, Uses = [CC] in {
+  def LOC  : CondUnaryRSY<"loc",  0xEBF2, GR32, 4>;
+  def LOCG : CondUnaryRSY<"locg", 0xEBE2, GR64, 8>;
+}
+let Uses = [CC] in {
+  def AsmLOC  : AsmCondUnaryRSY<"loc",  0xEBF2, GR32, 4>;
+  def AsmLOCG : AsmCondUnaryRSY<"locg", 0xEBE2, GR64, 8>;
+}
+defm : CondLoad<LOC,  GR32, nonvolatile_load>;
+defm : CondLoad<LOCG, GR64, nonvolatile_load>;
+
 // Register stores.
 let SimpleBDXStore = 1 in {
   let isCodeGenOnly = 1 in
diff --git a/llvm/lib/Target/SystemZ/SystemZOperands.td b/llvm/lib/Target/SystemZ/SystemZOperands.td
index 9d79439..696ec4f 100644
--- a/llvm/lib/Target/SystemZ/SystemZOperands.td
+++ b/llvm/lib/Target/SystemZ/SystemZOperands.td
@@ -111,6 +111,15 @@
                         !cast<Immediate>("imm"##bitsize))>;
 
 //===----------------------------------------------------------------------===//
+// Manipulating CC masks
+//===----------------------------------------------------------------------===//
+
+def INVCC : SDNodeXForm<imm, [{
+  unsigned Value = N->getZExtValue() ^ SystemZ::CCMASK_ANY;
+  return CurDAG->getTargetConstant(Value, MVT::i8);
+}]>;
+
+//===----------------------------------------------------------------------===//
 // Extracting immediate operands from nodes
 // These all create MVT::i64 nodes to ensure the value is not sign-extended
 // when converted from an SDNode to a MachineOperand later on.
diff --git a/llvm/lib/Target/SystemZ/SystemZPatterns.td b/llvm/lib/Target/SystemZ/SystemZPatterns.td
index 74cc5f0..4e4386a 100644
--- a/llvm/lib/Target/SystemZ/SystemZPatterns.td
+++ b/llvm/lib/Target/SystemZ/SystemZPatterns.td
@@ -54,6 +54,18 @@
   def : RMWI<anyextloadi8, operator, truncstorei8, mode, imm64, insn>;
 }
 
+// Record that INSN conditionally performs load operation LOAD into a
+// register of class CLS.  The load may trap even if the condition is false.
+multiclass CondLoad<Instruction insn, RegisterOperand cls,
+                    SDPatternOperator load> {
+  def : Pat<(z_select_ccmask (load bdaddr20only:$addr), cls:$new, uimm8zx4:$cc),
+            (insn cls:$new, bdaddr20only:$addr, uimm8zx4:$cc)>,
+        Requires<[FeatureLoadStoreOnCond]>;
+  def : Pat<(z_select_ccmask cls:$new, (load bdaddr20only:$addr), uimm8zx4:$cc),
+            (insn cls:$new, bdaddr20only:$addr, (INVCC uimm8zx4:$cc))>,
+        Requires<[FeatureLoadStoreOnCond]>;
+}
+
 // Record that INSN performs insertion TYPE into a register of class CLS.
 // The inserted operand is loaded using LOAD from an address of mode MODE.
 multiclass InsertMem<string type, Instruction insn, RegisterOperand cls,