mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-26 22:45:05 +00:00
ARM: Better codegen for 64-bit compares.
This introduces a custom lowering for ISD::SETCCE (introduced in r253572) that allows us to emit a short code sequence for 64-bit compares. Before: push {r7, lr} cmp r0, r2 mov.w r0, #0 mov.w r12, #0 it hs movhs r0, #1 cmp r1, r3 it ge movge.w r12, #1 it eq moveq r12, r0 cmp.w r12, #0 bne .LBB1_2 @ BB#1: @ %bb1 bl f pop {r7, pc} .LBB1_2: @ %bb2 bl g pop {r7, pc} After: push {r7, lr} subs r0, r0, r2 sbcs.w r0, r1, r3 bge .LBB1_2 @ BB#1: @ %bb1 bl f pop {r7, pc} .LBB1_2: @ %bb2 bl g pop {r7, pc} Saves around 80KB in Chromium's libchrome.so. Some notes on this patch: - I don't much like the ARMISD::BRCOND and ARMISD::CMOV combines I introduced (nothing else needs them). However, they are necessary in order to avoid poor codegen, and they seem similar to existing combines in other backends (e.g. X86 combines (brcond (cmp (setcc Compare))) to (brcond Compare)). - No support for Thumb-1. This is in principle possible, but we'd need to implement ARMISD::SUBE for Thumb-1. Differential Revision: http://reviews.llvm.org/D15256 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@263962 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
faf3d27a21
commit
f24c9d47b6
@ -919,6 +919,10 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
|
||||
|
||||
// Thumb-1 cannot currently select ARMISD::SUBE.
|
||||
if (!Subtarget->isThumb1Only())
|
||||
setOperationAction(ISD::SETCCE, MVT::i32, Custom);
|
||||
|
||||
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
|
||||
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::BR_CC, MVT::f32, Custom);
|
||||
@ -4898,6 +4902,30 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
static SDValue LowerSETCCE(SDValue Op, SelectionDAG &DAG) {
|
||||
SDValue LHS = Op.getOperand(0);
|
||||
SDValue RHS = Op.getOperand(1);
|
||||
SDValue Carry = Op.getOperand(2);
|
||||
SDValue Cond = Op.getOperand(3);
|
||||
SDLoc DL(Op);
|
||||
|
||||
assert(LHS.getSimpleValueType().isInteger() && "SETCCE is integer only.");
|
||||
|
||||
assert(Carry.getOpcode() != ISD::CARRY_FALSE);
|
||||
SDVTList VTs = DAG.getVTList(LHS.getValueType(), MVT::i32);
|
||||
SDValue Cmp = DAG.getNode(ARMISD::SUBE, DL, VTs, LHS, RHS, Carry);
|
||||
|
||||
SDValue FVal = DAG.getConstant(0, DL, MVT::i32);
|
||||
SDValue TVal = DAG.getConstant(1, DL, MVT::i32);
|
||||
SDValue ARMcc = DAG.getConstant(
|
||||
IntCCToARMCC(cast<CondCodeSDNode>(Cond)->get()), DL, MVT::i32);
|
||||
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
|
||||
SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, ARM::CPSR,
|
||||
Cmp.getValue(1), SDValue());
|
||||
return DAG.getNode(ARMISD::CMOV, DL, Op.getValueType(), FVal, TVal, ARMcc,
|
||||
CCR, Chain.getValue(1));
|
||||
}
|
||||
|
||||
/// isNEONModifiedImm - Check if the specified splat value corresponds to a
|
||||
/// valid vector constant for a NEON instruction with a "modified immediate"
|
||||
/// operand (e.g., VMOV). If so, return the encoded value.
|
||||
@ -7013,6 +7041,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
case ISD::CTTZ_ZERO_UNDEF: return LowerCTTZ(Op.getNode(), DAG, Subtarget);
|
||||
case ISD::CTPOP: return LowerCTPOP(Op.getNode(), DAG, Subtarget);
|
||||
case ISD::SETCC: return LowerVSETCC(Op, DAG);
|
||||
case ISD::SETCCE: return LowerSETCCE(Op, DAG);
|
||||
case ISD::ConstantFP: return LowerConstantFP(Op, DAG, Subtarget);
|
||||
case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG, Subtarget);
|
||||
case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
|
||||
@ -10639,6 +10668,46 @@ SDValue ARMTargetLowering::PerformCMOVToBFICombine(SDNode *CMOV, SelectionDAG &D
|
||||
return V;
|
||||
}
|
||||
|
||||
/// PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
|
||||
SDValue
|
||||
ARMTargetLowering::PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const {
|
||||
SDValue Cmp = N->getOperand(4);
|
||||
if (Cmp.getOpcode() != ARMISD::CMPZ)
|
||||
// Only looking at NE cases.
|
||||
return SDValue();
|
||||
|
||||
EVT VT = N->getValueType(0);
|
||||
SDLoc dl(N);
|
||||
SDValue LHS = Cmp.getOperand(0);
|
||||
SDValue RHS = Cmp.getOperand(1);
|
||||
SDValue Chain = N->getOperand(0);
|
||||
SDValue BB = N->getOperand(1);
|
||||
SDValue ARMcc = N->getOperand(2);
|
||||
ARMCC::CondCodes CC =
|
||||
(ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue();
|
||||
|
||||
// (brcond Chain BB ne CPSR (cmpz (and (cmov 0 1 CC CPSR Cmp) 1) 0))
|
||||
// -> (brcond Chain BB CC CPSR Cmp)
|
||||
if (CC == ARMCC::NE && LHS.getOpcode() == ISD::AND && LHS->hasOneUse() &&
|
||||
LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
|
||||
LHS->getOperand(0)->hasOneUse()) {
|
||||
auto *LHS00C = dyn_cast<ConstantSDNode>(LHS->getOperand(0)->getOperand(0));
|
||||
auto *LHS01C = dyn_cast<ConstantSDNode>(LHS->getOperand(0)->getOperand(1));
|
||||
auto *LHS1C = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
|
||||
auto *RHSC = dyn_cast<ConstantSDNode>(RHS);
|
||||
if ((LHS00C && LHS00C->getZExtValue() == 0) &&
|
||||
(LHS01C && LHS01C->getZExtValue() == 1) &&
|
||||
(LHS1C && LHS1C->getZExtValue() == 1) &&
|
||||
(RHSC && RHSC->getZExtValue() == 0)) {
|
||||
return DAG.getNode(
|
||||
ARMISD::BRCOND, dl, VT, Chain, BB, LHS->getOperand(0)->getOperand(2),
|
||||
LHS->getOperand(0)->getOperand(3), LHS->getOperand(0)->getOperand(4));
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
/// PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
|
||||
SDValue
|
||||
ARMTargetLowering::PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const {
|
||||
@ -10692,6 +10761,21 @@ ARMTargetLowering::PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const {
|
||||
N->getOperand(3), NewCmp);
|
||||
}
|
||||
|
||||
// (cmov F T ne CPSR (cmpz (cmov 0 1 CC CPSR Cmp) 0))
|
||||
// -> (cmov F T CC CPSR Cmp)
|
||||
if (CC == ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse()) {
|
||||
auto *LHS0C = dyn_cast<ConstantSDNode>(LHS->getOperand(0));
|
||||
auto *LHS1C = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
|
||||
auto *RHSC = dyn_cast<ConstantSDNode>(RHS);
|
||||
if ((LHS0C && LHS0C->getZExtValue() == 0) &&
|
||||
(LHS1C && LHS1C->getZExtValue() == 1) &&
|
||||
(RHSC && RHSC->getZExtValue() == 0)) {
|
||||
return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
|
||||
LHS->getOperand(2), LHS->getOperand(3),
|
||||
LHS->getOperand(4));
|
||||
}
|
||||
}
|
||||
|
||||
if (Res.getNode()) {
|
||||
APInt KnownZero, KnownOne;
|
||||
DAG.computeKnownBits(SDValue(N,0), KnownZero, KnownOne);
|
||||
@ -10742,6 +10826,7 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N,
|
||||
case ISD::ZERO_EXTEND:
|
||||
case ISD::ANY_EXTEND: return PerformExtendCombine(N, DCI.DAG, Subtarget);
|
||||
case ARMISD::CMOV: return PerformCMOVCombine(N, DCI.DAG);
|
||||
case ARMISD::BRCOND: return PerformBRCONDCombine(N, DCI.DAG);
|
||||
case ISD::LOAD: return PerformLOADCombine(N, DCI);
|
||||
case ARMISD::VLD2DUP:
|
||||
case ARMISD::VLD3DUP:
|
||||
|
@ -258,6 +258,7 @@ namespace llvm {
|
||||
SDNode *Node) const override;
|
||||
|
||||
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const;
|
||||
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const;
|
||||
SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const;
|
||||
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
|
||||
|
||||
|
@ -251,21 +251,18 @@ define i64 @test10(i64* %ptr, i64 %val) {
|
||||
; CHECK-LABEL: test10:
|
||||
; CHECK: dmb {{ish$}}
|
||||
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
|
||||
; CHECK: mov [[CARRY_LO:[a-z0-9]+]], #0
|
||||
; CHECK: mov [[CARRY_HI:[a-z0-9]+]], #0
|
||||
; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
|
||||
; CHECK-LE: cmp [[REG1]], r1
|
||||
; CHECK-BE: cmp [[REG2]], r2
|
||||
; CHECK: movwls [[CARRY_LO]], #1
|
||||
; CHECK-LE: cmp [[REG2]], r2
|
||||
; CHECK-BE: cmp [[REG1]], r1
|
||||
; CHECK: movwle [[CARRY_HI]], #1
|
||||
; CHECK: moveq [[CARRY_HI]], [[CARRY_LO]]
|
||||
; CHECK: cmp [[CARRY_HI]], #0
|
||||
; CHECK-LE: subs {{[^,]+}}, r1, [[REG1]]
|
||||
; CHECK-BE: subs {{[^,]+}}, r2, [[REG2]]
|
||||
; CHECK-LE: sbcs {{[^,]+}}, r2, [[REG2]]
|
||||
; CHECK-BE: sbcs {{[^,]+}}, r1, [[REG1]]
|
||||
; CHECK: mov [[CMP:[a-z0-9]+]], #0
|
||||
; CHECK: movwge [[CMP]], #1
|
||||
; CHECK: cmp [[CMP]], #0
|
||||
; CHECK: movne [[OUT_HI]], [[REG2]]
|
||||
; CHECK: mov [[OUT_LO:[a-z0-9]+]], r1
|
||||
; CHECK: movne [[OUT_LO]], [[REG1]]
|
||||
; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
|
||||
; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
|
||||
; CHECK: cmp
|
||||
; CHECK: bne
|
||||
; CHECK: dmb {{ish$}}
|
||||
@ -273,21 +270,18 @@ define i64 @test10(i64* %ptr, i64 %val) {
|
||||
; CHECK-THUMB-LABEL: test10:
|
||||
; CHECK-THUMB: dmb {{ish$}}
|
||||
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
|
||||
; CHECK-THUMB: mov.w [[CARRY_LO:[a-z0-9]+|lr]], #0
|
||||
; CHECK-THUMB: movs [[CARRY_HI:[a-z0-9]+|lr]], #0
|
||||
; CHECK-THUMB-LE: cmp [[REG1]], r2
|
||||
; CHECK-THUMB-BE: cmp [[REG2]], r3
|
||||
; CHECK-THUMB: movls.w [[CARRY_LO]], #1
|
||||
; CHECK-THUMB-LE: cmp [[REG2]], r3
|
||||
; CHECK-THUMB-BE: cmp [[REG1]], r2
|
||||
; CHECK-THUMB: movle [[CARRY_HI]], #1
|
||||
; CHECK-THUMB: moveq [[CARRY_HI]], [[CARRY_LO]]
|
||||
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
|
||||
; CHECK-THUMB: cmp [[CARRY_HI]], #0
|
||||
; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
|
||||
; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
|
||||
; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
|
||||
; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
|
||||
; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
|
||||
; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
|
||||
; CHECK-THUMB: mov.w [[CMP:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB: movge.w [[CMP]], #1
|
||||
; CHECK-THUMB: cmp.w [[CMP]], #0
|
||||
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
|
||||
; CHECK-THUMB: movne [[OUT_HI]], [[REG2]]
|
||||
; CHECK-THUMB: movne [[OUT_LO]], [[REG1]]
|
||||
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
|
||||
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
|
||||
; CHECK-THUMB: cmp
|
||||
; CHECK-THUMB: bne
|
||||
; CHECK-THUMB: dmb {{ish$}}
|
||||
@ -300,21 +294,18 @@ define i64 @test11(i64* %ptr, i64 %val) {
|
||||
; CHECK-LABEL: test11:
|
||||
; CHECK: dmb {{ish$}}
|
||||
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
|
||||
; CHECK: mov [[CARRY_LO:[a-z0-9]+]], #0
|
||||
; CHECK: mov [[CARRY_HI:[a-z0-9]+]], #0
|
||||
; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
|
||||
; CHECK-LE: cmp [[REG1]], r1
|
||||
; CHECK-BE: cmp [[REG2]], r2
|
||||
; CHECK: movwls [[CARRY_LO]], #1
|
||||
; CHECK-LE: cmp [[REG2]], r2
|
||||
; CHECK-BE: cmp [[REG1]], r1
|
||||
; CHECK: movwls [[CARRY_HI]], #1
|
||||
; CHECK: moveq [[CARRY_HI]], [[CARRY_LO]]
|
||||
; CHECK: cmp [[CARRY_HI]], #0
|
||||
; CHECK-LE: subs {{[^,]+}}, r1, [[REG1]]
|
||||
; CHECK-BE: subs {{[^,]+}}, r2, [[REG2]]
|
||||
; CHECK-LE: sbcs {{[^,]+}}, r2, [[REG2]]
|
||||
; CHECK-BE: sbcs {{[^,]+}}, r1, [[REG1]]
|
||||
; CHECK: mov [[CMP:[a-z0-9]+]], #0
|
||||
; CHECK: movwhs [[CMP]], #1
|
||||
; CHECK: cmp [[CMP]], #0
|
||||
; CHECK: movne [[OUT_HI]], [[REG2]]
|
||||
; CHECK: mov [[OUT_LO:[a-z0-9]+]], r1
|
||||
; CHECK: movne [[OUT_LO]], [[REG1]]
|
||||
; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
|
||||
; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
|
||||
; CHECK: cmp
|
||||
; CHECK: bne
|
||||
; CHECK: dmb {{ish$}}
|
||||
@ -322,21 +313,18 @@ define i64 @test11(i64* %ptr, i64 %val) {
|
||||
; CHECK-THUMB-LABEL: test11:
|
||||
; CHECK-THUMB: dmb {{ish$}}
|
||||
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
|
||||
; CHECK-THUMB: mov.w [[CARRY_LO:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB: movs [[CARRY_HI:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB-LE: cmp [[REG1]], r2
|
||||
; CHECK-THUMB-BE: cmp [[REG2]], r3
|
||||
; CHECK-THUMB: movls.w [[CARRY_LO]], #1
|
||||
; CHECK-THUMB-LE: cmp [[REG2]], r3
|
||||
; CHECK-THUMB-BE: cmp [[REG1]], r2
|
||||
; CHECK-THUMB: movls [[CARRY_HI]], #1
|
||||
; CHECK-THUMB: moveq [[CARRY_HI]], [[CARRY_LO]]
|
||||
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
|
||||
; CHECK-THUMB: cmp [[CARRY_HI]], #0
|
||||
; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
|
||||
; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
|
||||
; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
|
||||
; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
|
||||
; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
|
||||
; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
|
||||
; CHECK-THUMB: mov.w [[CMP:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB: movhs.w [[CMP]], #1
|
||||
; CHECK-THUMB: cmp.w [[CMP]], #0
|
||||
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
|
||||
; CHECK-THUMB: movne [[OUT_HI]], [[REG2]]
|
||||
; CHECK-THUMB: movne [[OUT_LO]], [[REG1]]
|
||||
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
|
||||
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
|
||||
; CHECK-THUMB: cmp
|
||||
; CHECK-THUMB: bne
|
||||
; CHECK-THUMB: dmb {{ish$}}
|
||||
@ -349,21 +337,18 @@ define i64 @test12(i64* %ptr, i64 %val) {
|
||||
; CHECK-LABEL: test12:
|
||||
; CHECK: dmb {{ish$}}
|
||||
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
|
||||
; CHECK: mov [[CARRY_LO:[a-z0-9]+]], #0
|
||||
; CHECK: mov [[CARRY_HI:[a-z0-9]+]], #0
|
||||
; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
|
||||
; CHECK-LE: cmp [[REG1]], r1
|
||||
; CHECK-BE: cmp [[REG2]], r2
|
||||
; CHECK: movwhi [[CARRY_LO]], #1
|
||||
; CHECK-LE: cmp [[REG2]], r2
|
||||
; CHECK-BE: cmp [[REG1]], r1
|
||||
; CHECK: movwgt [[CARRY_HI]], #1
|
||||
; CHECK: moveq [[CARRY_HI]], [[CARRY_LO]]
|
||||
; CHECK: cmp [[CARRY_HI]], #0
|
||||
; CHECK-LE: subs {{[^,]+}}, r1, [[REG1]]
|
||||
; CHECK-BE: subs {{[^,]+}}, r2, [[REG2]]
|
||||
; CHECK-LE: sbcs {{[^,]+}}, r2, [[REG2]]
|
||||
; CHECK-BE: sbcs {{[^,]+}}, r1, [[REG1]]
|
||||
; CHECK: mov [[CMP:[a-z0-9]+]], #0
|
||||
; CHECK: movwlt [[CMP]], #1
|
||||
; CHECK: cmp [[CMP]], #0
|
||||
; CHECK: movne [[OUT_HI]], [[REG2]]
|
||||
; CHECK: mov [[OUT_LO:[a-z0-9]+]], r1
|
||||
; CHECK: movne [[OUT_LO]], [[REG1]]
|
||||
; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
|
||||
; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
|
||||
; CHECK: cmp
|
||||
; CHECK: bne
|
||||
; CHECK: dmb {{ish$}}
|
||||
@ -371,21 +356,18 @@ define i64 @test12(i64* %ptr, i64 %val) {
|
||||
; CHECK-THUMB-LABEL: test12:
|
||||
; CHECK-THUMB: dmb {{ish$}}
|
||||
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
|
||||
; CHECK-THUMB: mov.w [[CARRY_LO:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB: movs [[CARRY_HI:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB-LE: cmp [[REG1]], r2
|
||||
; CHECK-THUMB-BE: cmp [[REG2]], r3
|
||||
; CHECK-THUMB: movhi.w [[CARRY_LO]], #1
|
||||
; CHECK-THUMB-LE: cmp [[REG2]], r3
|
||||
; CHECK-THUMB-BE: cmp [[REG1]], r2
|
||||
; CHECK-THUMB: movgt [[CARRY_HI]], #1
|
||||
; CHECK-THUMB: moveq [[CARRY_HI]], [[CARRY_LO]]
|
||||
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
|
||||
; CHECK-THUMB: cmp [[CARRY_HI]], #0
|
||||
; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
|
||||
; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
|
||||
; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
|
||||
; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
|
||||
; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
|
||||
; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
|
||||
; CHECK-THUMB: mov.w [[CMP:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB: movlt.w [[CMP]], #1
|
||||
; CHECK-THUMB: cmp.w [[CMP]], #0
|
||||
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
|
||||
; CHECK-THUMB: movne [[OUT_HI]], [[REG2]]
|
||||
; CHECK-THUMB: movne [[OUT_LO]], [[REG1]]
|
||||
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
|
||||
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
|
||||
; CHECK-THUMB: cmp
|
||||
; CHECK-THUMB: bne
|
||||
; CHECK-THUMB: dmb {{ish$}}
|
||||
@ -398,21 +380,18 @@ define i64 @test13(i64* %ptr, i64 %val) {
|
||||
; CHECK-LABEL: test13:
|
||||
; CHECK: dmb {{ish$}}
|
||||
; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
|
||||
; CHECK: mov [[CARRY_LO:[a-z0-9]+]], #0
|
||||
; CHECK: mov [[CARRY_HI:[a-z0-9]+]], #0
|
||||
; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
|
||||
; CHECK-LE: cmp [[REG1]], r1
|
||||
; CHECK-BE: cmp [[REG2]], r2
|
||||
; CHECK: movwhi [[CARRY_LO]], #1
|
||||
; CHECK-LE: cmp [[REG2]], r2
|
||||
; CHECK-BE: cmp [[REG1]], r1
|
||||
; CHECK: movwhi [[CARRY_HI]], #1
|
||||
; CHECK: moveq [[CARRY_HI]], [[CARRY_LO]]
|
||||
; CHECK: cmp [[CARRY_HI]], #0
|
||||
; CHECK-LE: subs {{[^,]+}}, r1, [[REG1]]
|
||||
; CHECK-BE: subs {{[^,]+}}, r2, [[REG2]]
|
||||
; CHECK-LE: sbcs {{[^,]+}}, r2, [[REG2]]
|
||||
; CHECK-BE: sbcs {{[^,]+}}, r1, [[REG1]]
|
||||
; CHECK: mov [[CMP:[a-z0-9]+]], #0
|
||||
; CHECK: movwlo [[CMP]], #1
|
||||
; CHECK: cmp [[CMP]], #0
|
||||
; CHECK: movne [[OUT_HI]], [[REG2]]
|
||||
; CHECK: mov [[OUT_LO:[a-z0-9]+]], r1
|
||||
; CHECK: movne [[OUT_LO]], [[REG1]]
|
||||
; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
|
||||
; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
|
||||
; CHECK: cmp
|
||||
; CHECK: bne
|
||||
; CHECK: dmb {{ish$}}
|
||||
@ -420,21 +399,18 @@ define i64 @test13(i64* %ptr, i64 %val) {
|
||||
; CHECK-THUMB-LABEL: test13:
|
||||
; CHECK-THUMB: dmb {{ish$}}
|
||||
; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
|
||||
; CHECK-THUMB: mov.w [[CARRY_LO:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB: movs [[CARRY_HI:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB-LE: cmp [[REG1]], r2
|
||||
; CHECK-THUMB-BE: cmp [[REG2]], r3
|
||||
; CHECK-THUMB: movhi.w [[CARRY_LO]], #1
|
||||
; CHECK-THUMB-LE: cmp [[REG2]], r3
|
||||
; CHECK-THUMB-BE: cmp [[REG1]], r2
|
||||
; CHECK-THUMB: movhi [[CARRY_HI]], #1
|
||||
; CHECK-THUMB: moveq [[CARRY_HI]], [[CARRY_LO]]
|
||||
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
|
||||
; CHECK-THUMB: cmp [[CARRY_HI]], #0
|
||||
; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
|
||||
; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
|
||||
; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
|
||||
; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
|
||||
; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
|
||||
; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
|
||||
; CHECK-THUMB: mov.w [[CMP:[a-z0-9]+]], #0
|
||||
; CHECK-THUMB: movlo.w [[CMP]], #1
|
||||
; CHECK-THUMB: cmp.w [[CMP]], #0
|
||||
; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
|
||||
; CHECK-THUMB: movne [[OUT_HI]], [[REG2]]
|
||||
; CHECK-THUMB: movne [[OUT_LO]], [[REG1]]
|
||||
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
|
||||
; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
|
||||
; CHECK-THUMB: cmp
|
||||
; CHECK-THUMB: bne
|
||||
; CHECK-THUMB: dmb {{ish$}}
|
||||
|
@ -667,19 +667,14 @@ define void @test_atomic_load_min_i64(i64 %offset) nounwind {
|
||||
; CHECK: ldaexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||||
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||||
; function there.
|
||||
; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM-LE: cmp [[OLD1]], r0
|
||||
; CHECK-ARM-LE: movwls [[LOCARRY]], #1
|
||||
; CHECK-ARM-LE: cmp [[OLD2]], r1
|
||||
; CHECK-ARM-LE: movwle [[HICARRY]], #1
|
||||
; CHECK-ARM-BE: cmp [[OLD2]], r1
|
||||
; CHECK-ARM-BE: movwls [[LOCARRY]], #1
|
||||
; CHECK-ARM-BE: cmp [[OLD1]], r0
|
||||
; CHECK-ARM-BE: movwle [[HICARRY]], #1
|
||||
; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
|
||||
; CHECK-ARM: cmp [[HICARRY]], #0
|
||||
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
|
||||
; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
|
||||
; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
|
||||
; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
|
||||
; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
|
||||
; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: movwge [[CMP:r[0-9]+|lr]], #1
|
||||
; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: movne [[MINHI]], [[OLD2]]
|
||||
; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
|
||||
; CHECK-ARM: movne [[MINLO]], [[OLD1]]
|
||||
@ -785,19 +780,14 @@ define void @test_atomic_load_max_i64(i64 %offset) nounwind {
|
||||
; CHECK: ldrexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||||
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||||
; function there.
|
||||
; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM-LE: cmp [[OLD1]], r0
|
||||
; CHECK-ARM-LE: movwhi [[LOCARRY]], #1
|
||||
; CHECK-ARM-LE: cmp [[OLD2]], r1
|
||||
; CHECK-ARM-LE: movwgt [[HICARRY]], #1
|
||||
; CHECK-ARM-BE: cmp [[OLD2]], r1
|
||||
; CHECK-ARM-BE: movwhi [[LOCARRY]], #1
|
||||
; CHECK-ARM-BE: cmp [[OLD1]], r0
|
||||
; CHECK-ARM-BE: movwgt [[HICARRY]], #1
|
||||
; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
|
||||
; CHECK-ARM: cmp [[HICARRY]], #0
|
||||
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
|
||||
; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
|
||||
; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
|
||||
; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
|
||||
; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
|
||||
; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: movwlt [[CMP:r[0-9]+|lr]], #1
|
||||
; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: movne [[MINHI]], [[OLD2]]
|
||||
; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
|
||||
; CHECK-ARM: movne [[MINLO]], [[OLD1]]
|
||||
@ -903,19 +893,14 @@ define void @test_atomic_load_umin_i64(i64 %offset) nounwind {
|
||||
; CHECK: ldaexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||||
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||||
; function there.
|
||||
; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM-LE: cmp [[OLD1]], r0
|
||||
; CHECK-ARM-LE: movwls [[LOCARRY]], #1
|
||||
; CHECK-ARM-LE: cmp [[OLD2]], r1
|
||||
; CHECK-ARM-LE: movwls [[HICARRY]], #1
|
||||
; CHECK-ARM-BE: cmp [[OLD2]], r1
|
||||
; CHECK-ARM-BE: movwls [[LOCARRY]], #1
|
||||
; CHECK-ARM-BE: cmp [[OLD1]], r0
|
||||
; CHECK-ARM-BE: movwls [[HICARRY]], #1
|
||||
; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
|
||||
; CHECK-ARM: cmp [[HICARRY]], #0
|
||||
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
|
||||
; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
|
||||
; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
|
||||
; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
|
||||
; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
|
||||
; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: movwhs [[CMP:r[0-9]+|lr]], #1
|
||||
; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: movne [[MINHI]], [[OLD2]]
|
||||
; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
|
||||
; CHECK-ARM: movne [[MINLO]], [[OLD1]]
|
||||
@ -1021,19 +1006,14 @@ define void @test_atomic_load_umax_i64(i64 %offset) nounwind {
|
||||
; CHECK: ldaexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||||
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||||
; function there.
|
||||
; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM-LE: cmp [[OLD1]], r0
|
||||
; CHECK-ARM-LE: movwhi [[LOCARRY]], #1
|
||||
; CHECK-ARM-LE: cmp [[OLD2]], r1
|
||||
; CHECK-ARM-LE: movwhi [[HICARRY]], #1
|
||||
; CHECK-ARM-BE: cmp [[OLD2]], r1
|
||||
; CHECK-ARM-BE: movwhi [[LOCARRY]], #1
|
||||
; CHECK-ARM-BE: cmp [[OLD1]], r0
|
||||
; CHECK-ARM-BE: movwhi [[HICARRY]], #1
|
||||
; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
|
||||
; CHECK-ARM: cmp [[HICARRY]], #0
|
||||
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
|
||||
; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
|
||||
; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
|
||||
; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
|
||||
; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
|
||||
; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: movwlo [[CMP:r[0-9]+|lr]], #1
|
||||
; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
|
||||
; CHECK-ARM: movne [[MINHI]], [[OLD2]]
|
||||
; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
|
||||
; CHECK-ARM: movne [[MINLO]], [[OLD1]]
|
||||
|
52
test/CodeGen/ARM/wide-compares.ll
Normal file
52
test/CodeGen/ARM/wide-compares.ll
Normal file
@ -0,0 +1,52 @@
|
||||
; RUN: llc -mtriple=armv7-unknown-linux < %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-ARM %s
|
||||
; RUN: llc -mtriple=thumbv6-unknown-linux < %s | FileCheck --check-prefix=CHECK-THUMB1 %s
|
||||
; RUN: llc -mtriple=thumbv7-unknown-linux < %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-THUMB2 %s
|
||||
|
||||
; CHECK-THUMB1-NOT: sbc
|
||||
|
||||
; CHECK-LABEL: test_slt1:
|
||||
define i32 @test_slt1(i64 %a, i64 %b) {
|
||||
entry:
|
||||
; CHECK-ARM: subs {{[^,]+}}, r0, r2
|
||||
; CHECK-ARM: mov [[TMP:[0-9a-z]+]], #2
|
||||
; CHECK-ARM: sbcs {{[^,]+}}, r1, r3
|
||||
; CHECK-ARM: movwlt [[TMP]], #1
|
||||
; CHECK-ARM: mov r0, [[TMP]]
|
||||
; CHECK-ARM: bx lr
|
||||
; CHECK-THUMB2: subs {{[^,]+}}, r0, r2
|
||||
; CHECK-THUMB2: mov.w [[TMP:[0-9a-z]+]], #2
|
||||
; CHECK-THUMB2: sbcs.w {{[^,]+}}, r1, r3
|
||||
; CHECK-THUMB2: it lt
|
||||
; CHECK-THUMB2: movlt.w [[TMP]], #1
|
||||
; CHECK-THUMB2: mov r0, [[TMP]]
|
||||
; CHECK-THUMB2: bx lr
|
||||
%cmp = icmp slt i64 %a, %b
|
||||
br i1 %cmp, label %bb1, label %bb2
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 2
|
||||
}
|
||||
|
||||
; CHECK-LABEL: test_slt2:
|
||||
define void @test_slt2(i64 %a, i64 %b) {
|
||||
entry:
|
||||
%cmp = icmp slt i64 %a, %b
|
||||
; CHECK-ARM: subs {{[^,]+}}, r0, r2
|
||||
; CHECK-ARM: sbcs {{[^,]+}}, r1, r3
|
||||
; CHECK-THUMB2: subs {{[^,]+}}, r0, r2
|
||||
; CHECK-THUMB2: sbcs.w {{[^,]+}}, r1, r3
|
||||
; CHECK: bge [[BB2:\.[0-9A-Za-z_]+]]
|
||||
br i1 %cmp, label %bb1, label %bb2
|
||||
bb1:
|
||||
call void @f()
|
||||
ret void
|
||||
bb2:
|
||||
; CHECK: [[BB2]]:
|
||||
; CHECK-NEXT: bl g
|
||||
call void @g()
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @f()
|
||||
declare void @g()
|
Loading…
x
Reference in New Issue
Block a user