summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp1
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp25
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.h1
-rw-r--r--llvm/lib/Target/ARM/ARMInstrInfo.td1
-rw-r--r--llvm/lib/Target/ARM/ARMInstrThumb.td6
-rw-r--r--llvm/test/CodeGen/Thumb/cmp-and-fold.ll10
6 files changed, 36 insertions, 8 deletions
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 222aa85856a..7b5e45f0ba2 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -2298,6 +2298,7 @@ static const AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[] = {
{ARM::tSUBSrr, ARM::tSUBrr},
{ARM::tSBCS, ARM::tSBC},
{ARM::tRSBS, ARM::tRSB},
+ {ARM::tLSLSri, ARM::tLSLri},
{ARM::t2ADDSri, ARM::t2ADDri},
{ARM::t2ADDSrr, ARM::t2ADDrr},
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index a87770125fd..e372bdb4f58 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1490,6 +1490,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
case ARMISD::ADDE: return "ARMISD::ADDE";
case ARMISD::SUBC: return "ARMISD::SUBC";
case ARMISD::SUBE: return "ARMISD::SUBE";
+ case ARMISD::LSLS: return "ARMISD::LSLS";
case ARMISD::VMOVRRD: return "ARMISD::VMOVRRD";
case ARMISD::VMOVDRR: return "ARMISD::VMOVDRR";
@@ -4110,6 +4111,30 @@ SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
}
}
}
+
+ // The specific comparison "(x<<c) > 0x80000000U" can be optimized to a
+ // single "lsls x, c+1". The shift sets the "C" and "Z" flags the same
+ // way a cmp would.
+ // FIXME: Add support for ARM/Thumb2; this would need isel patterns, and
+ // some tweaks to the heuristics for the previous and->shift transform.
+ // FIXME: Optimize cases where the LHS isn't a shift.
+ if (Subtarget->isThumb1Only() && LHS->getOpcode() == ISD::SHL &&
+ isa<ConstantSDNode>(RHS) &&
+ cast<ConstantSDNode>(RHS)->getZExtValue() == 0x80000000U &&
+ CC == ISD::SETUGT && isa<ConstantSDNode>(LHS.getOperand(1)) &&
+ cast<ConstantSDNode>(LHS.getOperand(1))->getZExtValue() < 31) {
+ unsigned ShiftAmt =
+ cast<ConstantSDNode>(LHS.getOperand(1))->getZExtValue() + 1;
+ SDValue Shift = DAG.getNode(ARMISD::LSLS, dl,
+ DAG.getVTList(MVT::i32, MVT::i32),
+ LHS.getOperand(0),
+ DAG.getConstant(ShiftAmt, dl, MVT::i32));
+ SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, ARM::CPSR,
+ Shift.getValue(1), SDValue());
+ ARMcc = DAG.getConstant(ARMCC::HI, dl, MVT::i32);
+ return Chain.getValue(1);
+ }
+
ARMCC::CondCodes CondCode = IntCCToARMCC(CC);
// If the RHS is a constant zero then the V (overflow) flag will never be
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index f584f9cfb9c..ae10bcd6cf0 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -103,6 +103,7 @@ class VectorType;
ADDE, // Add using carry
SUBC, // Sub with carry
SUBE, // Sub using carry
+ LSLS, // Shift left producing carry
VMOVRRD, // double to two gprs.
VMOVDRR, // Two gprs to double.
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index 0e3a9af56b1..7783bedc210 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -194,6 +194,7 @@ def ARMrrx : SDNode<"ARMISD::RRX" , SDTIntUnaryOp, [SDNPInGlue ]>;
def ARMaddc : SDNode<"ARMISD::ADDC", SDTBinaryArithWithFlags,
[SDNPCommutative]>;
def ARMsubc : SDNode<"ARMISD::SUBC", SDTBinaryArithWithFlags>;
+def ARMlsls : SDNode<"ARMISD::LSLS", SDTBinaryArithWithFlags>;
def ARMadde : SDNode<"ARMISD::ADDE", SDTBinaryArithWithFlagsInOut>;
def ARMsube : SDNode<"ARMISD::SUBE", SDTBinaryArithWithFlagsInOut>;
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td
index cfeb13c6acb..b3f4b34c73a 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb.td
@@ -1362,6 +1362,12 @@ let hasPostISelHook = 1, Defs = [CPSR] in {
[(set tGPR:$Rd, CPSR, (ARMsubc 0, tGPR:$Rn))]>,
Requires<[IsThumb1Only]>,
Sched<[WriteALU]>;
+
+ def tLSLSri : tPseudoInst<(outs tGPR:$Rd), (ins tGPR:$Rn, imm0_31:$imm5),
+ 2, IIC_iALUr,
+ [(set tGPR:$Rd, CPSR, (ARMlsls tGPR:$Rn, imm0_31:$imm5))]>,
+ Requires<[IsThumb1Only]>,
+ Sched<[WriteALU]>;
}
diff --git a/llvm/test/CodeGen/Thumb/cmp-and-fold.ll b/llvm/test/CodeGen/Thumb/cmp-and-fold.ll
index ba2e4fec9ac..44c873a5fe2 100644
--- a/llvm/test/CodeGen/Thumb/cmp-and-fold.ll
+++ b/llvm/test/CodeGen/Thumb/cmp-and-fold.ll
@@ -31,10 +31,7 @@ define void @test2(i32 %x, void ()* %f) {
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: .save {r7, lr}
; CHECK-NEXT: push {r7, lr}
-; CHECK-NEXT: movs r2, #1
-; CHECK-NEXT: lsls r2, r2, #31
-; CHECK-NEXT: lsls r0, r0, #7
-; CHECK-NEXT: cmp r0, r2
+; CHECK-NEXT: lsls r0, r0, #8
; CHECK-NEXT: bhi .LBB1_2
; CHECK-NEXT: @ %bb.1: @ %if.then
; CHECK-NEXT: blx r1
@@ -58,10 +55,7 @@ define void @test3(i32 %x, void ()* %f) {
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: .save {r7, lr}
; CHECK-NEXT: push {r7, lr}
-; CHECK-NEXT: movs r2, #1
-; CHECK-NEXT: lsls r2, r2, #31
-; CHECK-NEXT: lsls r0, r0, #2
-; CHECK-NEXT: cmp r0, r2
+; CHECK-NEXT: lsls r0, r0, #3
; CHECK-NEXT: bhi .LBB2_2
; CHECK-NEXT: @ %bb.1: @ %if.then
; CHECK-NEXT: blx r1
OpenPOWER on IntegriCloud