[llvm] r197234 - [SystemZ] Make more use of LTGFR

Richard Sandiford rsandifo at linux.vnet.ibm.com
Fri Dec 13 07:07:39 PST 2013


Author: rsandifo
Date: Fri Dec 13 09:07:39 2013
New Revision: 197234

URL: http://llvm.org/viewvc/llvm-project?rev=197234&view=rev
Log:
[SystemZ] Make more use of LTGFR

InstCombine turns (sext (trunc)) into (ashr (shl)), then converts any
comparison of the ashr against zero into a comparison of the shl against zero.
This makes sense in itself, but we want to undo it for z, since the sign-
extension instruction has a CC-setting form.

I've included tests for both the original and InstCombined variants,
but the former already worked.  The patch fixes the latter.

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

Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp?rev=197234&r1=197233&r2=197234&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp Fri Dec 13 09:07:39 2013
@@ -1280,6 +1280,36 @@ static void adjustForFNeg(SDValue &CmpOp
   }
 }
 
+// Check whether CmpOp0 is (shl X, 32), CmpOp1 is 0, and whether X is
+// also sign-extended.  In that case it is better to test the result
+// of the sign extension using LTGFR.
+//
+// This case is important because InstCombine transforms a comparison
+// with (sext (trunc X)) into a comparison with (shl X, 32).
+static void adjustForLTGFR(SDValue &CmpOp0, SDValue &CmpOp1,
+                           unsigned &IcmpType) {
+  // Check for a comparison between (shl X, 32) and 0.
+  if (CmpOp0.getOpcode() == ISD::SHL &&
+      CmpOp0.getValueType() == MVT::i64 &&
+      CmpOp1.getOpcode() == ISD::Constant &&
+      cast<ConstantSDNode>(CmpOp1)->getZExtValue() == 0) {
+    ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(CmpOp0.getOperand(1));
+    if (C1 && C1->getZExtValue() == 32) {
+      SDValue ShlOp0 = CmpOp0.getOperand(0);
+      // See whether X has any SIGN_EXTEND_INREG uses.
+      for (SDNode::use_iterator I = ShlOp0->use_begin(), E = ShlOp0->use_end();
+           I != E; ++I) {
+        SDNode *N = *I;
+        if (N->getOpcode() == ISD::SIGN_EXTEND_INREG &&
+            cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32) {
+          CmpOp0 = SDValue(N, 0);
+          return;
+        }
+      }
+    }
+  }
+}
+
 // 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) {
@@ -1497,6 +1527,7 @@ static SDValue emitCmp(const SystemZTarg
   adjustForTestUnderMask(DAG, Opcode, CmpOp0, CmpOp1, CCValid, CCMask,
                          ICmpType);
   adjustForFNeg(CmpOp0, CmpOp1, CCMask);
+  adjustForLTGFR(CmpOp0, CmpOp1, 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-44.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/int-cmp-44.ll?rev=197234&r1=197233&r2=197234&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/int-cmp-44.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/int-cmp-44.ll Fri Dec 13 09:07:39 2013
@@ -797,3 +797,51 @@ store:
 exit:
   ret i32 %val
 }
+
+; Test f35 for in-register extensions.
+define i64 @f39(i64 %dummy, i64 %a, i64 *%dest) {
+; CHECK-LABEL: f39:
+; CHECK: ltgfr %r2, %r3
+; CHECK-NEXT: #APP
+; CHECK-NEXT: blah %r2
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jh .L{{.*}}
+; CHECK: br %r14
+entry:
+  %val = trunc i64 %a to i32
+  %ext = sext i32 %val to i64
+  call void asm sideeffect "blah $0", "{r2}"(i64 %ext)
+  %cmp = icmp sgt i64 %ext, 0
+  br i1 %cmp, label %exit, label %store
+
+store:
+  store i64 %ext, i64 *%dest
+  br label %exit
+
+exit:
+  ret i64 %ext
+}
+
+; ...and again with what InstCombine would produce for f40.
+define i64 @f40(i64 %dummy, i64 %a, i64 *%dest) {
+; CHECK-LABEL: f40:
+; CHECK: ltgfr %r2, %r3
+; CHECK-NEXT: #APP
+; CHECK-NEXT: blah %r2
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jh .L{{.*}}
+; CHECK: br %r14
+entry:
+  %shl = shl i64 %a, 32
+  %ext = ashr i64 %shl, 32
+  call void asm sideeffect "blah $0", "{r2}"(i64 %ext)
+  %cmp = icmp sgt i64 %shl, 0
+  br i1 %cmp, label %exit, label %store
+
+store:
+  store i64 %ext, i64 *%dest
+  br label %exit
+
+exit:
+  ret i64 %ext
+}





More information about the llvm-commits mailing list