From 204537e25ebd13e5386c3ed6f62a160c7aa8390c Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 13 Dec 2013 15:07:39 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197234 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZISelLowering.cpp | 31 ++++++++++++++ test/CodeGen/SystemZ/int-cmp-44.ll | 48 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index 84b5009fd79..7d7536bffbe 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1280,6 +1280,36 @@ static void adjustForFNeg(SDValue &CmpOp0, SDValue &CmpOp1, unsigned &CCMask) { } } +// 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(CmpOp1)->getZExtValue() == 0) { + ConstantSDNode *C1 = dyn_cast(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(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 SystemZTargetMachine &TM, SelectionDAG &DAG, 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)); diff --git a/test/CodeGen/SystemZ/int-cmp-44.ll b/test/CodeGen/SystemZ/int-cmp-44.ll index ae0133f1086..7f537e9de75 100644 --- a/test/CodeGen/SystemZ/int-cmp-44.ll +++ b/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 +}