mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
[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. llvm-svn: 197234
This commit is contained in:
parent
123ebfd785
commit
3cb2e57bb5
@ -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));
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user