}
}
+// 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) {
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));
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
+}