[llvm] r190672 - [SystemZ] Try to fold shifts into TMxx

Richard Sandiford rsandifo at linux.vnet.ibm.com
Fri Sep 13 02:09:51 PDT 2013


Author: rsandifo
Date: Fri Sep 13 04:09:50 2013
New Revision: 190672

URL: http://llvm.org/viewvc/llvm-project?rev=190672&view=rev
Log:
[SystemZ] Try to fold shifts into TMxx

E.g. "SRL %r2, 2; TMLL %r2, 1" => "TMLL %r2, 4".

Modified:
    llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
    llvm/trunk/test/CodeGen/SystemZ/int-cmp-46.ll
    llvm/trunk/test/CodeGen/SystemZ/int-cmp-47.ll

Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp?rev=190672&r1=190671&r2=190672&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp Fri Sep 13 04:09:50 2013
@@ -1135,17 +1135,37 @@ static bool shouldSwapCmpOperands(SDValu
   return false;
 }
 
-// Check whether the CC value produced by TEST UNDER MASK is descriptive
-// enough to handle an AND with Mask followed by a comparison of type Opcode
-// with CmpVal.  CCMask says which comparison result is being tested and
-// BitSize is the number of bits in the operands.  Return the CC mask that
-// should be used for the TEST UNDER MASK result, or 0 if the condition is
-// too complex.
+// Return true if shift operation N has an in-range constant shift value.
+// Store it in ShiftVal if so.
+static bool isSimpleShift(SDValue N, unsigned &ShiftVal) {
+  ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N.getOperand(1));
+  if (!Shift)
+    return false;
+
+  uint64_t Amount = Shift->getZExtValue();
+  if (Amount >= N.getValueType().getSizeInBits())
+    return false;
+
+  ShiftVal = Amount;
+  return true;
+}
+
+// Check whether an AND with Mask is suitable for a TEST UNDER MASK
+// instruction and whether the CC value is descriptive enough to handle
+// a comparison of type Opcode between the AND result and CmpVal.
+// CCMask says which comparison result is being tested and BitSize is
+// the number of bits in the operands.  If TEST UNDER MASK can be used,
+// return the corresponding CC mask, otherwise return 0.
 static unsigned getTestUnderMaskCond(unsigned BitSize, unsigned CCMask,
                                      uint64_t Mask, uint64_t CmpVal,
                                      unsigned ICmpType) {
   assert(Mask != 0 && "ANDs with zero should have been removed by now");
 
+  // Check whether the mask is suitable for TMHH, TMHL, TMLH or TMLL.
+  if (!SystemZ::isImmLL(Mask) && !SystemZ::isImmLH(Mask) &&
+      !SystemZ::isImmHL(Mask) && !SystemZ::isImmHH(Mask))
+    return 0;
+
   // Work out the masks for the lowest and highest bits.
   unsigned HighShift = 63 - countLeadingZeros(Mask);
   uint64_t High = uint64_t(1) << HighShift;
@@ -1230,13 +1250,15 @@ static unsigned getTestUnderMaskCond(uns
 // implemented as a TEST UNDER MASK instruction when the condition being
 // tested is as described by CCValid and CCMask.  Update the arguments
 // with the TM version if so.
-static void adjustForTestUnderMask(unsigned &Opcode, SDValue &CmpOp0,
-                                   SDValue &CmpOp1, unsigned &CCValid,
-                                   unsigned &CCMask, unsigned &ICmpType) {
+static void adjustForTestUnderMask(SelectionDAG &DAG, unsigned &Opcode,
+                                   SDValue &CmpOp0, SDValue &CmpOp1,
+                                   unsigned &CCValid, unsigned &CCMask,
+                                   unsigned &ICmpType) {
   // Check that we have a comparison with a constant.
   ConstantSDNode *ConstCmpOp1 = dyn_cast<ConstantSDNode>(CmpOp1);
   if (!ConstCmpOp1)
     return;
+  uint64_t CmpVal = ConstCmpOp1->getZExtValue();
 
   // Check whether the nonconstant input is an AND with a constant mask.
   if (CmpOp0.getOpcode() != ISD::AND)
@@ -1246,21 +1268,35 @@ static void adjustForTestUnderMask(unsig
   ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(AndOp1.getNode());
   if (!Mask)
     return;
-
-  // Check whether the mask is suitable for TMHH, TMHL, TMLH or TMLL.
   uint64_t MaskVal = Mask->getZExtValue();
-  if (!SystemZ::isImmLL(MaskVal) && !SystemZ::isImmLH(MaskVal) &&
-      !SystemZ::isImmHL(MaskVal) && !SystemZ::isImmHH(MaskVal))
-    return;
 
   // Check whether the combination of mask, comparison value and comparison
   // type are suitable.
   unsigned BitSize = CmpOp0.getValueType().getSizeInBits();
-  unsigned NewCCMask = getTestUnderMaskCond(BitSize, CCMask, MaskVal,
-                                            ConstCmpOp1->getZExtValue(),
-                                            ICmpType);
-  if (!NewCCMask)
-    return;
+  unsigned NewCCMask, ShiftVal;
+  if (ICmpType != SystemZICMP::SignedOnly &&
+      AndOp0.getOpcode() == ISD::SHL &&
+      isSimpleShift(AndOp0, ShiftVal) &&
+      (NewCCMask = getTestUnderMaskCond(BitSize, CCMask, MaskVal >> ShiftVal,
+                                        CmpVal >> ShiftVal,
+                                        SystemZICMP::Any))) {
+    AndOp0 = AndOp0.getOperand(0);
+    AndOp1 = DAG.getConstant(MaskVal >> ShiftVal, AndOp0.getValueType());
+  } else if (ICmpType != SystemZICMP::SignedOnly &&
+             AndOp0.getOpcode() == ISD::SRL &&
+             isSimpleShift(AndOp0, ShiftVal) &&
+             (NewCCMask = getTestUnderMaskCond(BitSize, CCMask,
+                                               MaskVal << ShiftVal,
+                                               CmpVal << ShiftVal,
+                                               SystemZICMP::UnsignedOnly))) {
+    AndOp0 = AndOp0.getOperand(0);
+    AndOp1 = DAG.getConstant(MaskVal << ShiftVal, AndOp0.getValueType());
+  } else {
+    NewCCMask = getTestUnderMaskCond(BitSize, CCMask, MaskVal, CmpVal,
+                                     ICmpType);
+    if (!NewCCMask)
+      return;
+  }
 
   // Go ahead and make the change.
   Opcode = SystemZISD::TM;
@@ -1316,7 +1352,8 @@ static SDValue emitCmp(const SystemZTarg
               (CCMask & SystemZ::CCMASK_CMP_UO));
   }
 
-  adjustForTestUnderMask(Opcode, CmpOp0, CmpOp1, CCValid, CCMask, ICmpType);
+  adjustForTestUnderMask(DAG, Opcode, CmpOp0, CmpOp1, CCValid, CCMask,
+                         ICmpType);
   if (Opcode == SystemZISD::ICMP || Opcode == SystemZISD::TM)
     return DAG.getNode(Opcode, DL, MVT::Glue, CmpOp0, CmpOp1,
                        DAG.getConstant(ICmpType, MVT::i32));

Modified: llvm/trunk/test/CodeGen/SystemZ/int-cmp-46.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/int-cmp-46.ll?rev=190672&r1=190671&r2=190672&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/int-cmp-46.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/int-cmp-46.ll Fri Sep 13 04:09:50 2013
@@ -449,3 +449,43 @@ store:
 exit:
   ret void
 }
+
+; Check that we can fold an SHL into a TMxx mask.
+define void @f24(i32 %a) {
+; CHECK-LABEL: f24:
+; CHECK: tmll %r2, 255
+; CHECK: jne {{\.L.*}}
+; CHECK: br %r14
+entry:
+  %shl = shl i32 %a, 12
+  %and = and i32 %shl, 1044480
+  %cmp = icmp ne i32 %and, 0
+  br i1 %cmp, label %exit, label %store
+
+store:
+  store i32 1, i32 *@g
+  br label %exit
+
+exit:
+  ret void
+}
+
+; Check that we can fold an SHR into a TMxx mask.
+define void @f25(i32 %a) {
+; CHECK-LABEL: f25:
+; CHECK: tmlh %r2, 512
+; CHECK: jne {{\.L.*}}
+; CHECK: br %r14
+entry:
+  %shr = lshr i32 %a, 25
+  %and = and i32 %shr, 1
+  %cmp = icmp ne i32 %and, 0
+  br i1 %cmp, label %exit, label %store
+
+store:
+  store i32 1, i32 *@g
+  br label %exit
+
+exit:
+  ret void
+}

Modified: llvm/trunk/test/CodeGen/SystemZ/int-cmp-47.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/int-cmp-47.ll?rev=190672&r1=190671&r2=190672&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/int-cmp-47.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/int-cmp-47.ll Fri Sep 13 04:09:50 2013
@@ -191,3 +191,43 @@ store:
 exit:
   ret void
 }
+
+; Check that we can fold an SHL into a TMxx mask.
+define void @f11(i64 %a) {
+; CHECK-LABEL: f11:
+; CHECK: tmhl %r2, 32768
+; CHECK: jne {{\.L.*}}
+; CHECK: br %r14
+entry:
+  %shl = shl i64 %a, 1
+  %and = and i64 %shl, 281474976710656
+  %cmp = icmp ne i64 %and, 0
+  br i1 %cmp, label %exit, label %store
+
+store:
+  store i32 1, i32 *@g
+  br label %exit
+
+exit:
+  ret void
+}
+
+; Check that we can fold an SHR into a TMxx mask.
+define void @f12(i64 %a) {
+; CHECK-LABEL: f12:
+; CHECK: tmhh %r2, 256
+; CHECK: jne {{\.L.*}}
+; CHECK: br %r14
+entry:
+  %shr = lshr i64 %a, 56
+  %and = and i64 %shr, 1
+  %cmp = icmp ne i64 %and, 0
+  br i1 %cmp, label %exit, label %store
+
+store:
+  store i32 1, i32 *@g
+  br label %exit
+
+exit:
+  ret void
+}





More information about the llvm-commits mailing list