[llvm] r197234 - [SystemZ] Make more use of LTGFR
Richard Sandiford
rsandifo at linux.vnet.ibm.com
Fri Dec 13 07:07:39 PST 2013
Author: rsandifo
Date: Fri Dec 13 09:07:39 2013
New Revision: 197234
URL: http://llvm.org/viewvc/llvm-project?rev=197234&view=rev
Log:
[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.
Modified:
llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
llvm/trunk/test/CodeGen/SystemZ/int-cmp-44.ll
Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp?rev=197234&r1=197233&r2=197234&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp Fri Dec 13 09:07:39 2013
@@ -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));
Modified: llvm/trunk/test/CodeGen/SystemZ/int-cmp-44.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/int-cmp-44.ll?rev=197234&r1=197233&r2=197234&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/int-cmp-44.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/int-cmp-44.ll Fri Dec 13 09:07:39 2013
@@ -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
+}
More information about the llvm-commits
mailing list