File backport-llvm-r197234 of Package llvm

------------------------------------------------------------------------
r197234 | rsandifo | 2013-12-13 16:07:39 +0100 (Fri, 13 Dec 2013) | 10 lines

[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.

------------------------------------------------------------------------
Index: test/CodeGen/SystemZ/int-cmp-44.ll
===================================================================
--- test/CodeGen/SystemZ/int-cmp-44.ll.orig
+++ test/CodeGen/SystemZ/int-cmp-44.ll
@@ -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
+}
Index: lib/Target/SystemZ/SystemZISelLowering.cpp
===================================================================
--- lib/Target/SystemZ/SystemZISelLowering.cpp.orig
+++ lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -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));
openSUSE Build Service is sponsored by