[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
This commit is contained in:
Richard Sandiford 2013-12-13 15:07:39 +00:00
parent fd2b2bd6b3
commit 204537e25e
2 changed files with 79 additions and 0 deletions

View File

@ -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<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 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));

View File

@ -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
}