Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -7437,6 +7437,11 @@ SDVTList VTs = DAG.getVTList(VT, MVT::i32); SDValue Carry = Op.getOperand(2); + + // Let the target independent generic combiner work for us. + if (isNullConstant(Carry)) + return SDValue(); + EVT CarryVT = Carry.getValueType(); SDLoc DL(Op); @@ -9999,6 +10004,17 @@ } } + if (N->getOpcode() == ARMISD::SUBC) { + // (SUBC (ADDE 0, 0, C), 1) -> C + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + if (LHS->getOpcode() == ARMISD::ADDE && + isNullConstant(LHS->getOperand(0)) && + isNullConstant(LHS->getOperand(1)) && isOneConstant(RHS)) { + return DCI.CombineTo(N, SDValue(N, 0), LHS->getOperand(2)); + } + } + if (Subtarget->isThumb1Only()) { SDValue RHS = N->getOperand(1); if (ConstantSDNode *C = dyn_cast(RHS)) { @@ -12223,6 +12239,91 @@ } } + if (!VT.isInteger()) + return SDValue(); + + // Materialize a boolean comparison for integers so we can avoid branching. + if (isNullConstant(FalseVal)) { + if (CC == ARMCC::EQ && isOneConstant(TrueVal)) { + if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) { + // If x == y then x - y == 0 and ARM's CLZ will return 32, shifting it + // right 5 bits will make that 32 be 1, otherwise it will be 0. + // CMOV 0, 1, ==, (CMPZ x, y) -> SRL (CTLZ (SUB x, y)), 5 + SDValue Sub = DAG.getNode(ISD::SUB, dl, VT, LHS, RHS); + Res = DAG.getNode(ISD::SRL, dl, VT, DAG.getNode(ISD::CTLZ, dl, VT, Sub), + DAG.getConstant(5, dl, MVT::i32)); + } else { + // CMOV 0, 1, ==, (CMPZ x, y) -> + // (ADDCARRY (SUB x, y), t:0, t:1) + // where t = (SUBCARRY 0, (SUB x, y), 0) + // + // The SUBCARRY computes 0 - (x - y) and this will give a borrow when + // x != y. In other words, a carry C == 1 when x == y, C == 0 + // otherwise. + // The final ADDCARRY computes + // x - y + (0 - (x - y)) + C == C + SDValue Sub = DAG.getNode(ISD::SUB, dl, VT, LHS, RHS); + SDVTList VTs = DAG.getVTList(VT, MVT::i32); + SDValue Neg = DAG.getNode(ISD::SUBCARRY, dl, VTs, FalseVal, Sub, + DAG.getConstant(0, dl, MVT::i32)); + // ISD::SUBCARRY returns a borrow but we want the carry here + // actually. + SDValue Carry = + DAG.getNode(ISD::SUB, dl, MVT::i32, + DAG.getConstant(1, dl, MVT::i32), Neg.getValue(1)); + Res = DAG.getNode(ISD::ADDCARRY, dl, VTs, Sub, Neg, Carry); + } + } else if (CC == ARMCC::NE && LHS != RHS && + (!Subtarget->isThumb1Only() || isPowerOf2Constant(TrueVal))) { + // This seems pointless but will allow us to combine it further below. + // CMOV 0, z, !=, (CMPZ x, y) -> CMOV (SUB x, y), z, !=, (CMPZ x, y) + SDValue Sub = DAG.getNode(ISD::SUB, dl, VT, LHS, RHS); + Res = DAG.getNode(ARMISD::CMOV, dl, VT, Sub, TrueVal, ARMcc, + N->getOperand(3), Cmp); + } + } else if (isNullConstant(TrueVal)) { + if (CC == ARMCC::EQ && LHS != RHS && + (!Subtarget->isThumb1Only() || isPowerOf2Constant(FalseVal))) { + // This seems pointless but will allow us to combine it further below + // Note that we change == for != as this is the dual for the case above. + // CMOV z, 0, ==, (CMPZ x, y) -> CMOV (SUB x, y), z, !=, (CMPZ x, y) + SDValue Sub = DAG.getNode(ISD::SUB, dl, VT, LHS, RHS); + Res = DAG.getNode(ARMISD::CMOV, dl, VT, Sub, FalseVal, + DAG.getConstant(ARMCC::NE, dl, MVT::i32), + N->getOperand(3), Cmp); + } + } + + // On Thumb1, the DAG above may be further combined if z is a power of 2 + // (z == 2 ^ K). + // CMOV (SUB x, y), z, !=, (CMPZ x, y) -> + // merge t3, t4 + // where t1 = (SUBCARRY (SUB x, y), z, 0) + // t2 = (SUBCARRY (SUB x, y), t1:0, t1:1) + // t3 = if K != 0 then (SHL t2:0, K) else t2:0 + // t4 = (SUB 1, t2:1) [ we want a carry, not a borrow ] + const APInt *TrueConst; + if (Subtarget->isThumb1Only() && CC == ARMCC::NE && + (FalseVal.getOpcode() == ISD::SUB) && (FalseVal.getOperand(0) == LHS) && + (FalseVal.getOperand(1) == RHS) && + (TrueConst = isPowerOf2Constant(TrueVal))) { + SDVTList VTs = DAG.getVTList(VT, MVT::i32); + unsigned ShiftAmount = TrueConst->logBase2(); + if (ShiftAmount) + TrueVal = DAG.getConstant(1, dl, VT); + SDValue Subc = DAG.getNode(ISD::SUBCARRY, dl, VTs, FalseVal, TrueVal, + DAG.getConstant(0, dl, MVT::i32)); + Res = DAG.getNode(ISD::SUBCARRY, dl, VTs, FalseVal, Subc, Subc.getValue(1)); + // Make it a carry, not a borrow. + SDValue Carry = DAG.getNode( + ISD::SUB, dl, VT, DAG.getConstant(1, dl, MVT::i32), Res.getValue(1)); + Res = DAG.getNode(ISD::MERGE_VALUES, dl, VTs, Res, Carry); + + if (ShiftAmount) + Res = DAG.getNode(ISD::SHL, dl, VT, Res, + DAG.getConstant(ShiftAmount, dl, MVT::i32)); + } + if (Res.getNode()) { KnownBits Known; DAG.computeKnownBits(SDValue(N,0), Known); Index: test/CodeGen/ARM/and-load-combine.ll =================================================================== --- test/CodeGen/ARM/and-load-combine.ll +++ test/CodeGen/ARM/and-load-combine.ll @@ -9,34 +9,31 @@ ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldrh r0, [r0] ; ARM-NEXT: ldrh r1, [r1] -; ARM-NEXT: eor r1, r1, r0 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, #255 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: eor r0, r1, r0 +; ARM-NEXT: uxtb r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_xor8_short_short: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldrh r0, [r0] ; ARMEB-NEXT: ldrh r1, [r1] -; ARMEB-NEXT: eor r1, r1, r0 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, #255 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: eor r0, r1, r0 +; ARMEB-NEXT: uxtb r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_xor8_short_short: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldrh r0, [r0] -; THUMB1-NEXT: ldrh r2, [r1] -; THUMB1-NEXT: eors r2, r0 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #24 -; THUMB1-NEXT: beq .LBB0_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB0_2: @ %entry +; THUMB1-NEXT: ldrh r1, [r1] +; THUMB1-NEXT: eors r1, r0 +; THUMB1-NEXT: uxtb r1, r1 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_xor8_short_short: @@ -44,10 +41,9 @@ ; THUMB2-NEXT: ldrh r0, [r0] ; THUMB2-NEXT: ldrh r1, [r1] ; THUMB2-NEXT: eors r0, r1 -; THUMB2-NEXT: lsls r0, r0, #24 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxtb r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i16* nocapture readonly %b) { entry: @@ -64,34 +60,31 @@ ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldrh r0, [r0] ; ARM-NEXT: ldr r1, [r1] -; ARM-NEXT: eor r1, r1, r0 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, #255 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: eor r0, r1, r0 +; ARM-NEXT: uxtb r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_xor8_short_int: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldrh r0, [r0] ; ARMEB-NEXT: ldr r1, [r1] -; ARMEB-NEXT: eor r1, r1, r0 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, #255 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: eor r0, r1, r0 +; ARMEB-NEXT: uxtb r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_xor8_short_int: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldrh r0, [r0] -; THUMB1-NEXT: ldr r2, [r1] -; THUMB1-NEXT: eors r2, r0 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #24 -; THUMB1-NEXT: beq .LBB1_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB1_2: @ %entry +; THUMB1-NEXT: ldr r1, [r1] +; THUMB1-NEXT: eors r1, r0 +; THUMB1-NEXT: uxtb r1, r1 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_xor8_short_int: @@ -99,10 +92,9 @@ ; THUMB2-NEXT: ldrh r0, [r0] ; THUMB2-NEXT: ldr r1, [r1] ; THUMB2-NEXT: eors r0, r1 -; THUMB2-NEXT: lsls r0, r0, #24 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxtb r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i32* nocapture readonly %b) { entry: @@ -120,34 +112,31 @@ ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldr r0, [r0] ; ARM-NEXT: ldr r1, [r1] -; ARM-NEXT: eor r1, r1, r0 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, #255 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: eor r0, r1, r0 +; ARM-NEXT: uxtb r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_xor8_int_int: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldr r0, [r0] ; ARMEB-NEXT: ldr r1, [r1] -; ARMEB-NEXT: eor r1, r1, r0 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, #255 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: eor r0, r1, r0 +; ARMEB-NEXT: uxtb r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_xor8_int_int: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldr r0, [r0] -; THUMB1-NEXT: ldr r2, [r1] -; THUMB1-NEXT: eors r2, r0 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #24 -; THUMB1-NEXT: beq .LBB2_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB2_2: @ %entry +; THUMB1-NEXT: ldr r1, [r1] +; THUMB1-NEXT: eors r1, r0 +; THUMB1-NEXT: uxtb r1, r1 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_xor8_int_int: @@ -155,10 +144,9 @@ ; THUMB2-NEXT: ldr r0, [r0] ; THUMB2-NEXT: ldr r1, [r1] ; THUMB2-NEXT: eors r0, r1 -; THUMB2-NEXT: lsls r0, r0, #24 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxtb r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i32* nocapture readonly %b) { entry: @@ -174,37 +162,32 @@ ; ARM-LABEL: cmp_xor16: ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldr r0, [r0] -; ARM-NEXT: movw r2, #65535 ; ARM-NEXT: ldr r1, [r1] -; ARM-NEXT: eor r1, r1, r0 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, r2 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: eor r0, r1, r0 +; ARM-NEXT: uxth r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_xor16: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldr r0, [r0] -; ARMEB-NEXT: movw r2, #65535 ; ARMEB-NEXT: ldr r1, [r1] -; ARMEB-NEXT: eor r1, r1, r0 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, r2 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: eor r0, r1, r0 +; ARMEB-NEXT: uxth r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_xor16: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldr r0, [r0] -; THUMB1-NEXT: ldr r2, [r1] -; THUMB1-NEXT: eors r2, r0 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #16 -; THUMB1-NEXT: beq .LBB3_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB3_2: @ %entry +; THUMB1-NEXT: ldr r1, [r1] +; THUMB1-NEXT: eors r1, r0 +; THUMB1-NEXT: uxth r1, r1 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_xor16: @@ -212,10 +195,9 @@ ; THUMB2-NEXT: ldr r0, [r0] ; THUMB2-NEXT: ldr r1, [r1] ; THUMB2-NEXT: eors r0, r1 -; THUMB2-NEXT: lsls r0, r0, #16 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxth r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i32* nocapture readonly %b) { entry: @@ -232,34 +214,31 @@ ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldrh r0, [r0] ; ARM-NEXT: ldrh r1, [r1] -; ARM-NEXT: orr r1, r1, r0 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, #255 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: orr r0, r1, r0 +; ARM-NEXT: uxtb r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_or8_short_short: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldrh r0, [r0] ; ARMEB-NEXT: ldrh r1, [r1] -; ARMEB-NEXT: orr r1, r1, r0 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, #255 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: orr r0, r1, r0 +; ARMEB-NEXT: uxtb r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_or8_short_short: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldrh r0, [r0] -; THUMB1-NEXT: ldrh r2, [r1] -; THUMB1-NEXT: orrs r2, r0 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #24 -; THUMB1-NEXT: beq .LBB4_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB4_2: @ %entry +; THUMB1-NEXT: ldrh r1, [r1] +; THUMB1-NEXT: orrs r1, r0 +; THUMB1-NEXT: uxtb r1, r1 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_or8_short_short: @@ -267,10 +246,9 @@ ; THUMB2-NEXT: ldrh r0, [r0] ; THUMB2-NEXT: ldrh r1, [r1] ; THUMB2-NEXT: orrs r0, r1 -; THUMB2-NEXT: lsls r0, r0, #24 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxtb r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i16* nocapture readonly %b) { entry: @@ -287,34 +265,31 @@ ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldrh r0, [r0] ; ARM-NEXT: ldr r1, [r1] -; ARM-NEXT: orr r1, r1, r0 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, #255 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: orr r0, r1, r0 +; ARM-NEXT: uxtb r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_or8_short_int: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldrh r0, [r0] ; ARMEB-NEXT: ldr r1, [r1] -; ARMEB-NEXT: orr r1, r1, r0 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, #255 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: orr r0, r1, r0 +; ARMEB-NEXT: uxtb r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_or8_short_int: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldrh r0, [r0] -; THUMB1-NEXT: ldr r2, [r1] -; THUMB1-NEXT: orrs r2, r0 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #24 -; THUMB1-NEXT: beq .LBB5_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB5_2: @ %entry +; THUMB1-NEXT: ldr r1, [r1] +; THUMB1-NEXT: orrs r1, r0 +; THUMB1-NEXT: uxtb r1, r1 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_or8_short_int: @@ -322,10 +297,9 @@ ; THUMB2-NEXT: ldrh r0, [r0] ; THUMB2-NEXT: ldr r1, [r1] ; THUMB2-NEXT: orrs r0, r1 -; THUMB2-NEXT: lsls r0, r0, #24 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxtb r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i32* nocapture readonly %b) { entry: @@ -343,34 +317,31 @@ ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldr r0, [r0] ; ARM-NEXT: ldr r1, [r1] -; ARM-NEXT: orr r1, r1, r0 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, #255 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: orr r0, r1, r0 +; ARM-NEXT: uxtb r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_or8_int_int: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldr r0, [r0] ; ARMEB-NEXT: ldr r1, [r1] -; ARMEB-NEXT: orr r1, r1, r0 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, #255 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: orr r0, r1, r0 +; ARMEB-NEXT: uxtb r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_or8_int_int: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldr r0, [r0] -; THUMB1-NEXT: ldr r2, [r1] -; THUMB1-NEXT: orrs r2, r0 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #24 -; THUMB1-NEXT: beq .LBB6_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB6_2: @ %entry +; THUMB1-NEXT: ldr r1, [r1] +; THUMB1-NEXT: orrs r1, r0 +; THUMB1-NEXT: uxtb r1, r1 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_or8_int_int: @@ -378,10 +349,9 @@ ; THUMB2-NEXT: ldr r0, [r0] ; THUMB2-NEXT: ldr r1, [r1] ; THUMB2-NEXT: orrs r0, r1 -; THUMB2-NEXT: lsls r0, r0, #24 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxtb r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i32* nocapture readonly %b) { entry: @@ -397,37 +367,32 @@ ; ARM-LABEL: cmp_or16: ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldr r0, [r0] -; ARM-NEXT: movw r2, #65535 ; ARM-NEXT: ldr r1, [r1] -; ARM-NEXT: orr r1, r1, r0 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, r2 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: orr r0, r1, r0 +; ARM-NEXT: uxth r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_or16: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldr r0, [r0] -; ARMEB-NEXT: movw r2, #65535 ; ARMEB-NEXT: ldr r1, [r1] -; ARMEB-NEXT: orr r1, r1, r0 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, r2 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: orr r0, r1, r0 +; ARMEB-NEXT: uxth r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_or16: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldr r0, [r0] -; THUMB1-NEXT: ldr r2, [r1] -; THUMB1-NEXT: orrs r2, r0 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #16 -; THUMB1-NEXT: beq .LBB7_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB7_2: @ %entry +; THUMB1-NEXT: ldr r1, [r1] +; THUMB1-NEXT: orrs r1, r0 +; THUMB1-NEXT: uxth r1, r1 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_or16: @@ -435,10 +400,9 @@ ; THUMB2-NEXT: ldr r0, [r0] ; THUMB2-NEXT: ldr r1, [r1] ; THUMB2-NEXT: orrs r0, r1 -; THUMB2-NEXT: lsls r0, r0, #16 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxth r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i32* nocapture readonly %b) { entry: @@ -455,34 +419,31 @@ ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldrh r1, [r1] ; ARM-NEXT: ldrh r0, [r0] -; ARM-NEXT: and r1, r0, r1 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, #255 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: and r0, r0, r1 +; ARM-NEXT: uxtb r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_and8_short_short: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldrh r1, [r1] ; ARMEB-NEXT: ldrh r0, [r0] -; ARMEB-NEXT: and r1, r0, r1 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, #255 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: and r0, r0, r1 +; ARMEB-NEXT: uxtb r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_and8_short_short: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldrh r1, [r1] -; THUMB1-NEXT: ldrh r2, [r0] -; THUMB1-NEXT: ands r2, r1 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #24 -; THUMB1-NEXT: beq .LBB8_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB8_2: @ %entry +; THUMB1-NEXT: ldrh r0, [r0] +; THUMB1-NEXT: ands r0, r1 +; THUMB1-NEXT: uxtb r1, r0 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_and8_short_short: @@ -490,10 +451,9 @@ ; THUMB2-NEXT: ldrh r1, [r1] ; THUMB2-NEXT: ldrh r0, [r0] ; THUMB2-NEXT: ands r0, r1 -; THUMB2-NEXT: lsls r0, r0, #24 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxtb r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i16* nocapture readonly %b) { entry: @@ -510,34 +470,31 @@ ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldrh r0, [r0] ; ARM-NEXT: ldr r1, [r1] -; ARM-NEXT: and r1, r1, r0 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, #255 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: and r0, r1, r0 +; ARM-NEXT: uxtb r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_and8_short_int: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldrh r0, [r0] ; ARMEB-NEXT: ldr r1, [r1] -; ARMEB-NEXT: and r1, r1, r0 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, #255 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: and r0, r1, r0 +; ARMEB-NEXT: uxtb r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_and8_short_int: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldrh r0, [r0] -; THUMB1-NEXT: ldr r2, [r1] -; THUMB1-NEXT: ands r2, r0 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #24 -; THUMB1-NEXT: beq .LBB9_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB9_2: @ %entry +; THUMB1-NEXT: ldr r1, [r1] +; THUMB1-NEXT: ands r1, r0 +; THUMB1-NEXT: uxtb r1, r1 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_and8_short_int: @@ -545,10 +502,9 @@ ; THUMB2-NEXT: ldrh r0, [r0] ; THUMB2-NEXT: ldr r1, [r1] ; THUMB2-NEXT: ands r0, r1 -; THUMB2-NEXT: lsls r0, r0, #24 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxtb r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i32* nocapture readonly %b) { entry: @@ -566,34 +522,31 @@ ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldr r1, [r1] ; ARM-NEXT: ldr r0, [r0] -; ARM-NEXT: and r1, r0, r1 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, #255 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: and r0, r0, r1 +; ARM-NEXT: uxtb r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_and8_int_int: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldr r1, [r1] ; ARMEB-NEXT: ldr r0, [r0] -; ARMEB-NEXT: and r1, r0, r1 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, #255 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: and r0, r0, r1 +; ARMEB-NEXT: uxtb r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_and8_int_int: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldr r1, [r1] -; THUMB1-NEXT: ldr r2, [r0] -; THUMB1-NEXT: ands r2, r1 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #24 -; THUMB1-NEXT: beq .LBB10_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB10_2: @ %entry +; THUMB1-NEXT: ldr r0, [r0] +; THUMB1-NEXT: ands r0, r1 +; THUMB1-NEXT: uxtb r1, r0 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_and8_int_int: @@ -601,10 +554,9 @@ ; THUMB2-NEXT: ldr r1, [r1] ; THUMB2-NEXT: ldr r0, [r0] ; THUMB2-NEXT: ands r0, r1 -; THUMB2-NEXT: lsls r0, r0, #24 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxtb r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i32* nocapture readonly %b) { entry: @@ -620,37 +572,32 @@ ; ARM-LABEL: cmp_and16: ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldr r1, [r1] -; ARM-NEXT: movw r2, #65535 ; ARM-NEXT: ldr r0, [r0] -; ARM-NEXT: and r1, r0, r1 -; ARM-NEXT: mov r0, #0 -; ARM-NEXT: tst r1, r2 -; ARM-NEXT: movweq r0, #1 +; ARM-NEXT: and r0, r0, r1 +; ARM-NEXT: uxth r0, r0 +; ARM-NEXT: clz r0, r0 +; ARM-NEXT: lsr r0, r0, #5 ; ARM-NEXT: bx lr ; ; ARMEB-LABEL: cmp_and16: ; ARMEB: @ %bb.0: @ %entry ; ARMEB-NEXT: ldr r1, [r1] -; ARMEB-NEXT: movw r2, #65535 ; ARMEB-NEXT: ldr r0, [r0] -; ARMEB-NEXT: and r1, r0, r1 -; ARMEB-NEXT: mov r0, #0 -; ARMEB-NEXT: tst r1, r2 -; ARMEB-NEXT: movweq r0, #1 +; ARMEB-NEXT: and r0, r0, r1 +; ARMEB-NEXT: uxth r0, r0 +; ARMEB-NEXT: clz r0, r0 +; ARMEB-NEXT: lsr r0, r0, #5 ; ARMEB-NEXT: bx lr ; ; THUMB1-LABEL: cmp_and16: ; THUMB1: @ %bb.0: @ %entry ; THUMB1-NEXT: ldr r1, [r1] -; THUMB1-NEXT: ldr r2, [r0] -; THUMB1-NEXT: ands r2, r1 -; THUMB1-NEXT: movs r0, #1 -; THUMB1-NEXT: movs r1, #0 -; THUMB1-NEXT: lsls r2, r2, #16 -; THUMB1-NEXT: beq .LBB11_2 -; THUMB1-NEXT: @ %bb.1: @ %entry -; THUMB1-NEXT: mov r0, r1 -; THUMB1-NEXT: .LBB11_2: @ %entry +; THUMB1-NEXT: ldr r0, [r0] +; THUMB1-NEXT: ands r0, r1 +; THUMB1-NEXT: uxth r1, r0 +; THUMB1-NEXT: movs r0, #0 +; THUMB1-NEXT: subs r0, r0, r1 +; THUMB1-NEXT: adcs r0, r1 ; THUMB1-NEXT: bx lr ; ; THUMB2-LABEL: cmp_and16: @@ -658,10 +605,9 @@ ; THUMB2-NEXT: ldr r1, [r1] ; THUMB2-NEXT: ldr r0, [r0] ; THUMB2-NEXT: ands r0, r1 -; THUMB2-NEXT: lsls r0, r0, #16 -; THUMB2-NEXT: mov.w r0, #0 -; THUMB2-NEXT: it eq -; THUMB2-NEXT: moveq r0, #1 +; THUMB2-NEXT: uxth r0, r0 +; THUMB2-NEXT: clz r0, r0 +; THUMB2-NEXT: lsrs r0, r0, #5 ; THUMB2-NEXT: bx lr i32* nocapture readonly %b) { entry: Index: test/CodeGen/ARM/atomic-cmpxchg.ll =================================================================== --- test/CodeGen/ARM/atomic-cmpxchg.ll +++ test/CodeGen/ARM/atomic-cmpxchg.ll @@ -16,20 +16,17 @@ ; CHECK-ARM-LABEL: test_cmpxchg_res_i8 ; CHECK-ARM: bl __sync_val_compare_and_swap_1 -; CHECK-ARM: mov [[REG:r[0-9]+]], #0 -; CHECK-ARM: cmp r0, {{r[0-9]+}} -; CHECK-ARM: moveq [[REG]], #1 -; CHECK-ARM: mov r0, [[REG]] +; CHECK-ARM: sub r0, r0, {{r[0-9]+}} +; CHECK-ARM: rsbs [[REG:r[0-9]+]], r0, #0 +; CHECK-ARM: adc r0, r0, [[REG]] ; CHECK-THUMB-LABEL: test_cmpxchg_res_i8 ; CHECK-THUMB: bl __sync_val_compare_and_swap_1 ; CHECK-THUMB-NOT: mov [[R1:r[0-7]]], r0 -; CHECK-THUMB: movs [[R1:r[0-7]]], r0 -; CHECK-THUMB: movs r0, #1 -; CHECK-THUMB: movs [[R2:r[0-9]+]], #0 -; CHECK-THUMB: cmp [[R1]], {{r[0-9]+}} -; CHECK-THUMB: beq -; CHECK-THUMB: movs r0, [[R2]] +; CHECK-THUMB: subs [[R1:r[0-7]]], r0, {{r[0-9]+}} +; CHECK-THUMB: movs r0, #0 +; CHECK-THUMB: subs r0, r0, [[R1]] +; CHECK-THUMB: adcs r0, [[R1]] ; CHECK-ARMV6-LABEL: test_cmpxchg_res_i8: ; CHECK-ARMV6-NEXT: .fnstart @@ -48,14 +45,10 @@ ; CHECK-THUMBV6-LABEL: test_cmpxchg_res_i8: ; CHECK-THUMBV6: mov [[EXPECTED:r[0-9]+]], r1 ; CHECK-THUMBV6-NEXT: bl __sync_val_compare_and_swap_1 -; CHECK-THUMBV6-NEXT: mov [[RES:r[0-9]+]], r0 -; CHECK-THUMBV6-NEXT: movs r0, #1 -; CHECK-THUMBV6-NEXT: movs [[ZERO:r[0-9]+]], #0 -; CHECK-THUMBV6-NEXT: cmp [[RES]], [[EXPECTED]] -; CHECK-THUMBV6-NEXT: beq [[END:.LBB[0-9_]+]] -; CHECK-THUMBV6-NEXT: mov r0, [[ZERO]] -; CHECK-THUMBV6-NEXT: [[END]]: -; CHECK-THUMBV6-NEXT: pop {{.*}}pc} +; CHECK-THUMBV6-NEXT: subs [[R1:r[0-7]]], r0, {{r[0-9]+}} +; CHECK-THUMBV6-NEXT: movs r0, #0 +; CHECK-THUMBV6-NEXT: subs r0, r0, [[R1]] +; CHECK-THUMBV6-NEXT: adcs r0, [[R1]] ; CHECK-ARMV7-LABEL: test_cmpxchg_res_i8: ; CHECK-ARMV7-NEXT: .fnstart Index: test/CodeGen/ARM/cmn.ll =================================================================== --- test/CodeGen/ARM/cmn.ll +++ test/CodeGen/ARM/cmn.ll @@ -7,8 +7,8 @@ ; CHECK-NOT: mvn ; CHECK: cmn %cmp = icmp sgt i32 %a, -78 - %. = zext i1 %cmp to i32 - ret i32 %. + %ret = select i1 %cmp, i32 42, i32 24 + ret i32 %ret } define i32 @compare_r_eq(i32 %a, i32 %b) { @@ -17,6 +17,6 @@ ; CHECK: cmn %sub = sub nsw i32 0, %b %cmp = icmp eq i32 %a, %sub - %. = zext i1 %cmp to i32 - ret i32 %. + %ret = select i1 %cmp, i32 42, i32 24 + ret i32 %ret } Index: test/CodeGen/ARM/cmp.ll =================================================================== --- test/CodeGen/ARM/cmp.ll +++ test/CodeGen/ARM/cmp.ll @@ -3,42 +3,35 @@ define i1 @f1(i32 %a, i32 %b) { ; CHECK-LABEL: f1: -; CHECK: mov r2, #0 -; CHECK: cmp r0, r1 -; CHECK: movwne r2, #1 -; CHECK: mov r0, r2 -; CHECK-T2: mov{{.*}} r2, #0 -; CHECK-T2: cmp r0, r1 -; CHECK-T2: movne r2, #1 -; CHECK-T2: mov r0, r2 +; CHECK: subs r0, r0, r1 +; CHECK: movwne r0, #1 +; CHECK-T2: subs r0, r0, r1 +; CHECK-T2: it ne +; CHECK-T2: movne r0, #1 %tmp = icmp ne i32 %a, %b ret i1 %tmp } define i1 @f2(i32 %a, i32 %b) { ; CHECK-LABEL: f2: -; CHECK: mov r2, #0 -; CHECK: cmp r0, r1 -; CHECK: movweq r2, #1 -; CHECK: mov r0, r2 -; CHECK-T2: mov{{.*}} r2, #0 -; CHECK-T2: cmp r0, r1 -; CHECK-T2: moveq r2, #1 -; CHECK-T2: mov r0, r2 +; CHECK: sub r0, r0, r1 +; CHECK: clz r0, r0 +; CHECK: lsr r0, r0, #5 +; CHECK-T2: subs r0, r0, r1 +; CHECK-T2: clz r0, r0 +; CHECK-T2: lsrs r0, r0, #5 %tmp = icmp eq i32 %a, %b ret i1 %tmp } define i1 @f6(i32 %a, i32 %b) { ; CHECK-LABEL: f6: -; CHECK: mov r2, #0 -; CHECK: cmp {{.*}}, r1, lsl #5 -; CHECK: movweq r2, #1 -; CHECK: mov r0, r2 -; CHECK-T2: mov{{.*}} r2, #0 -; CHECK-T2: cmp.w r0, r1, lsl #5 -; CHECK-T2: moveq r2, #1 -; CHECK-T2: mov r0, r2 +; CHECK: sub r0, r0, r1, lsl #5 +; CHECK: clz r0, r0 +; CHECK: lsr r0, r0, #5 +; CHECK-T2: sub.w r0, r0, r1, lsl #5 +; CHECK-T2: clz r0, r0 +; CHECK-T2: lsrs r0, r0, #5 %tmp = shl i32 %b, 5 %tmp1 = icmp eq i32 %a, %tmp ret i1 %tmp1 @@ -46,14 +39,15 @@ define i1 @f7(i32 %a, i32 %b) { ; CHECK-LABEL: f7: -; CHECK: mov r2, #0 -; CHECK: cmp r0, r1, lsr #6 -; CHECK: movwne r2, #1 -; CHECK: mov r0, r2 -; CHECK-T2: mov{{.*}} r2, #0 -; CHECK-T2: cmp.w r0, r1, lsr #6 -; CHECK-T2: movne r2, #1 -; CHECK-T2: mov r0, r2 +; CHECK: sub r2, r0, r1, lsr #6 +; CHECK: cmp r0, r1, lsr #6 +; CHECK: movwne r2, #1 +; CHECK: mov r0, r2 +; CHECK-T2: sub.w r2, r0, r1, lsr #6 +; CHECK-T2: cmp.w r0, r1, lsr #6 +; CHECK-T2: it ne +; CHECK-T2: movne r2, #1 +; CHECK-T2: mov r0, r2 %tmp = lshr i32 %b, 6 %tmp1 = icmp ne i32 %a, %tmp ret i1 %tmp1 @@ -61,14 +55,12 @@ define i1 @f8(i32 %a, i32 %b) { ; CHECK-LABEL: f8: -; CHECK: mov r2, #0 -; CHECK: cmp r0, r1, asr #7 -; CHECK: movweq r2, #1 -; CHECK: mov r0, r2 -; CHECK-T2: mov{{.*}} r2, #0 -; CHECK-T2: cmp.w r0, r1, asr #7 -; CHECK-T2: moveq r2, #1 -; CHECK-T2: mov r0, r2 +; CHECK: sub r0, r0, r1, asr #7 +; CHECK: clz r0, r0 +; CHECK: lsr r0, r0, #5 +; CHECK-T2: sub.w r0, r0, r1, asr #7 +; CHECK-T2: clz r0, r0 +; CHECK-T2: lsrs r0, r0, #5 %tmp = ashr i32 %b, 7 %tmp1 = icmp eq i32 %a, %tmp ret i1 %tmp1 @@ -76,14 +68,15 @@ define i1 @f9(i32 %a) { ; CHECK-LABEL: f9: -; CHECK: mov r1, #0 -; CHECK: cmp r0, r0, ror #8 -; CHECK: movwne r1, #1 -; CHECK: mov r0, r1 -; CHECK-T2: mov{{.*}} r1, #0 -; CHECK-T2: cmp.w r0, r0, ror #8 -; CHECK-T2: movne r1, #1 -; CHECK-T2: mov r0, r1 +; CHECK: sub r1, r0, r0, ror #8 +; CHECK: cmp r0, r0, ror #8 +; CHECK: movwne r1, #1 +; CHECK: mov r0, r1 +; CHECK-T2: sub.w r1, r0, r0, ror #8 +; CHECK-T2: cmp.w r0, r0, ror #8 +; CHECK-T2: it ne +; CHECK-T2: movne r1, #1 +; CHECK-T2: mov r0, r1 %l8 = shl i32 %a, 24 %r8 = lshr i32 %a, 8 %tmp = or i32 %l8, %r8 Index: test/CodeGen/ARM/cmpxchg-O0.ll =================================================================== --- test/CodeGen/ARM/cmpxchg-O0.ll +++ test/CodeGen/ARM/cmpxchg-O0.ll @@ -17,8 +17,10 @@ ; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 ; CHECK: bne [[RETRY]] ; CHECK: [[DONE]]: -; CHECK: cmp{{(\.w)?}} [[OLD]], [[DESIRED]] -; CHECK: {{moveq|movweq}} {{r[0-9]+}}, #1 +; Materialisation of a boolean is done with sub/clz/lsr +; CHECK: sub{{(s)?}} [[CMP1:r[0-9]+]], [[OLD]], [[DESIRED]] +; CHECK: clz [[CMP2:r[0-9]+]], [[CMP1]] +; CHECK: lsr{{(s)?}} {{r[0-9]+}}, [[CMP2]], #5 ; CHECK: dmb ish %res = cmpxchg i8* %addr, i8 %desired, i8 %new seq_cst monotonic ret { i8, i1 } %res @@ -36,8 +38,10 @@ ; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 ; CHECK: bne [[RETRY]] ; CHECK: [[DONE]]: -; CHECK: cmp{{(\.w)?}} [[OLD]], [[DESIRED]] -; CHECK: {{moveq|movweq}} {{r[0-9]+}}, #1 +; Materialisation of a boolean is done with sub/clz/lsr +; CHECK: sub{{(s)?}} [[CMP1:r[0-9]+]], [[OLD]], [[DESIRED]] +; CHECK: clz [[CMP2:r[0-9]+]], [[CMP1]] +; CHECK: lsr{{(s)?}} {{r[0-9]+}}, [[CMP2]], #5 ; CHECK: dmb ish %res = cmpxchg i16* %addr, i16 %desired, i16 %new seq_cst monotonic ret { i16, i1 } %res @@ -55,8 +59,10 @@ ; CHECK: cmp{{(\.w)?}} [[STATUS]], #0 ; CHECK: bne [[RETRY]] ; CHECK: [[DONE]]: -; CHECK: cmp{{(\.w)?}} [[OLD]], [[DESIRED]] -; CHECK: {{moveq|movweq}} {{r[0-9]+}}, #1 +; Materialisation of a boolean is done with sub/clz/lsr +; CHECK: sub{{(s)?}} [[CMP1:r[0-9]+]], [[OLD]], [[DESIRED]] +; CHECK: clz [[CMP2:r[0-9]+]], [[CMP1]] +; CHECK: lsr{{(s)?}} {{r[0-9]+}}, [[CMP2]], #5 ; CHECK: dmb ish %res = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst monotonic ret { i32, i1 } %res Index: test/CodeGen/ARM/fp16-promote.ll =================================================================== --- test/CodeGen/ARM/fp16-promote.ll +++ test/CodeGen/ARM/fp16-promote.ll @@ -170,8 +170,10 @@ ; CHECK-LIBCALL: bl __aeabi_h2f ; CHECK-VFP: vcmp.f32 ; CHECK-NOVFP: bl __aeabi_fcmpeq -; CHECK-FP16: vmrs APSR_nzcv, fpscr -; CHECK-ALL: movw{{ne|eq}} +; CHECK-VFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-VFP-NEXT: movwne +; CHECK-NOVFP-NEXT: clz r0, r0 +; CHECK-NOVFP-NEXT: lsr r0, r0, #5 define i1 @test_fcmp_une(half* %p, half* %q) #0 { %a = load half, half* %p, align 2 %b = load half, half* %q, align 2 Index: test/CodeGen/ARM/long-setcc.ll =================================================================== --- test/CodeGen/ARM/long-setcc.ll +++ test/CodeGen/ARM/long-setcc.ll @@ -1,20 +1,26 @@ ; RUN: llc -mtriple=arm-eabi < %s | FileCheck %s define i1 @t1(i64 %x) { +; CHECK-LABEL: t1: +; CHECK: lsr r0, r1, #31 %B = icmp slt i64 %x, 0 ret i1 %B } define i1 @t2(i64 %x) { +; CHECK-LABEL: t2: +; CHECK: rsbs r0, r1, #0 +; CHECK: adc r0, r1, r0 %tmp = icmp ult i64 %x, 4294967296 ret i1 %tmp } define i1 @t3(i32 %x) { +; CHECK-LABEL: t3: +; CHECK: mov r0, #0 %tmp = icmp ugt i32 %x, -1 ret i1 %tmp } -; CHECK: cmp ; CHECK-NOT: cmp Index: test/CodeGen/ARM/select-imm.ll =================================================================== --- test/CodeGen/ARM/select-imm.ll +++ test/CodeGen/ARM/select-imm.ll @@ -49,16 +49,17 @@ define i32 @t3(i32 %a) nounwind readnone { entry: ; ARM-LABEL: t3: -; ARM: mov [[R:r[0-1]]], #0 -; ARM: moveq [[R]], #1 +; ARM: rsbs r1, r0, #0 +; ARM: adc r0, r0, r1 ; ARMT2-LABEL: t3: -; ARMT2: mov [[R:r[0-1]]], #0 -; ARMT2: movweq [[R]], #1 +; ARMT2: clz r0, r0 +; ARMT2: lsr r0, r0, #5 + ; THUMB2-LABEL: t3: -; THUMB2: mov{{(s|\.w)}} [[R:r[0-1]]], #0 -; THUMB2: moveq [[R]], #1 +; THUMB2: clz r0, r0 +; THUMB2: lsrs r0, r0, #5 %0 = icmp eq i32 %a, 160 %1 = zext i1 %0 to i32 ret i32 %1 @@ -86,15 +87,17 @@ entry: ; ARM-LABEL: t5: ; ARM-NOT: mov -; ARM: cmp r0, #1 +; ARM: sub r0, r0, #1 ; ARM-NOT: mov -; ARM: movne r0, #0 +; ARM: rsbs r1, r0, #0 +; ARM: adc r0, r0, r1 ; THUMB2-LABEL: t5: ; THUMB2-NOT: mov -; THUMB2: cmp r0, #1 -; THUMB2: it ne -; THUMB2: movne r0, #0 +; THUMB2: subs r0, #1 +; THUMB2: clz r0, r0 +; THUMB2: lsrs r0, r0, #5 + %cmp = icmp eq i32 %a, 1 %conv = zext i1 %cmp to i32 ret i32 %conv Index: test/CodeGen/ARM/setcc-logic.ll =================================================================== --- test/CodeGen/ARM/setcc-logic.ll +++ test/CodeGen/ARM/setcc-logic.ll @@ -20,12 +20,12 @@ define zeroext i1 @and_eq(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { ; CHECK-LABEL: and_eq: ; CHECK: @ %bb.0: -; CHECK-NEXT: eor r2, r2, r3 -; CHECK-NEXT: eor r0, r0, r1 -; CHECK-NEXT: orrs r0, r0, r2 -; CHECK-NEXT: mov r0, #0 -; CHECK-NEXT: movweq r0, #1 -; CHECK-NEXT: bx lr +; CHECK: eor r2, r2, r3 +; CHECK: eor r0, r0, r1 +; CHECK: orr r0, r0, r2 +; CHECK: clz r0, r0 +; CHECK: lsr r0, r0, #5 +; CHECK: bx lr %cmp1 = icmp eq i32 %a, %b %cmp2 = icmp eq i32 %c, %d %and = and i1 %cmp1, %cmp2 Index: test/CodeGen/Thumb/long-setcc.ll =================================================================== --- test/CodeGen/Thumb/long-setcc.ll +++ test/CodeGen/Thumb/long-setcc.ll @@ -15,8 +15,5 @@ ret i1 %tmp } -; CHECK: cmp ; CHECK-NOT: cmp - - Index: test/CodeGen/Thumb2/float-cmp.ll =================================================================== --- test/CodeGen/Thumb2/float-cmp.ll +++ test/CodeGen/Thumb2/float-cmp.ll @@ -69,7 +69,8 @@ ; HARD: movvc r0, #1 %1 = fcmp ord float %a, %b ret i1 %1 -}define i1 @cmp_f_ueq(float %a, float %b) { +} +define i1 @cmp_f_ueq(float %a, float %b) { ; CHECK-LABEL: cmp_f_ueq: ; NONE: bl __aeabi_fcmpeq ; NONE: bl __aeabi_fcmpun @@ -82,8 +83,8 @@ define i1 @cmp_f_ugt(float %a, float %b) { ; CHECK-LABEL: cmp_f_ugt: ; NONE: bl __aeabi_fcmple -; NONE: cmp r0, #0 -; NONE-NEXT: it eq +; NONE-NEXT: clz r0, r0 +; NONE-NEXT: lsrs r0, r0, #5 ; HARD: vcmpe.f32 ; HARD: movhi r0, #1 %1 = fcmp ugt float %a, %b @@ -92,8 +93,8 @@ define i1 @cmp_f_uge(float %a, float %b) { ; CHECK-LABEL: cmp_f_uge: ; NONE: bl __aeabi_fcmplt -; NONE: cmp r0, #0 -; NONE-NEXT: it eq +; NONE-NEXT: clz r0, r0 +; NONE-NEXT: lsrs r0, r0, #5 ; HARD: vcmpe.f32 ; HARD: movpl r0, #1 %1 = fcmp uge float %a, %b @@ -102,8 +103,8 @@ define i1 @cmp_f_ult(float %a, float %b) { ; CHECK-LABEL: cmp_f_ult: ; NONE: bl __aeabi_fcmpge -; NONE: cmp r0, #0 -; NONE-NEXT: it eq +; NONE-NEXT: clz r0, r0 +; NONE-NEXT: lsrs r0, r0, #5 ; HARD: vcmpe.f32 ; HARD: movlt r0, #1 %1 = fcmp ult float %a, %b @@ -112,8 +113,8 @@ define i1 @cmp_f_ule(float %a, float %b) { ; CHECK-LABEL: cmp_f_ule: ; NONE: bl __aeabi_fcmpgt -; NONE: cmp r0, #0 -; NONE-NEXT: it eq +; NONE-NEXT: clz r0, r0 +; NONE-NEXT: lsrs r0, r0, #5 ; HARD: vcmpe.f32 ; HARD: movle r0, #1 %1 = fcmp ule float %a, %b Index: test/CodeGen/Thumb2/thumb2-cmn.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-cmn.ll +++ test/CodeGen/Thumb2/thumb2-cmn.ll @@ -3,72 +3,80 @@ ; These tests could be improved by 'movs r0, #0' being rematerialized below the ; test as 'mov.w r0, #0'. -define i1 @f1(i32 %a, i32 %b) { +define i32 @f1(i32 %a, i32 %b) { %nb = sub i32 0, %b %tmp = icmp ne i32 %a, %nb - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f1: ; CHECK: cmn {{.*}}, r1 -define i1 @f2(i32 %a, i32 %b) { +define i32 @f2(i32 %a, i32 %b) { %nb = sub i32 0, %b %tmp = icmp ne i32 %nb, %a - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f2: ; CHECK: cmn {{.*}}, r1 -define i1 @f3(i32 %a, i32 %b) { +define i32 @f3(i32 %a, i32 %b) { %nb = sub i32 0, %b %tmp = icmp eq i32 %a, %nb - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f3: ; CHECK: cmn {{.*}}, r1 -define i1 @f4(i32 %a, i32 %b) { +define i32 @f4(i32 %a, i32 %b) { %nb = sub i32 0, %b %tmp = icmp eq i32 %nb, %a - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f4: ; CHECK: cmn {{.*}}, r1 -define i1 @f5(i32 %a, i32 %b) { +define i32 @f5(i32 %a, i32 %b) { %tmp = shl i32 %b, 5 %nb = sub i32 0, %tmp %tmp1 = icmp eq i32 %nb, %a - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f5: ; CHECK: cmn.w {{.*}}, r1, lsl #5 -define i1 @f6(i32 %a, i32 %b) { +define i32 @f6(i32 %a, i32 %b) { %tmp = lshr i32 %b, 6 %nb = sub i32 0, %tmp %tmp1 = icmp ne i32 %nb, %a - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f6: ; CHECK: cmn.w {{.*}}, r1, lsr #6 -define i1 @f7(i32 %a, i32 %b) { +define i32 @f7(i32 %a, i32 %b) { %tmp = ashr i32 %b, 7 %nb = sub i32 0, %tmp %tmp1 = icmp eq i32 %a, %nb - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f7: ; CHECK: cmn.w {{.*}}, r1, asr #7 -define i1 @f8(i32 %a, i32 %b) { +define i32 @f8(i32 %a, i32 %b) { %l8 = shl i32 %a, 24 %r8 = lshr i32 %a, 8 %tmp = or i32 %l8, %r8 %nb = sub i32 0, %tmp %tmp1 = icmp ne i32 %a, %nb - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f8: ; CHECK: cmn.w {{.*}}, {{.*}}, ror #8 Index: test/CodeGen/Thumb2/thumb2-cmn2.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-cmn2.ll +++ test/CodeGen/Thumb2/thumb2-cmn2.ll @@ -1,33 +1,37 @@ ; RUN: llc -mtriple=thumb-eabi -mcpu=arm1156t2-s -mattr=+thumb2 %s -o - | FileCheck %s ; -0x000000bb = 4294967109 -define i1 @f1(i32 %a) { +define i32 @f1(i32 %a) { ; CHECK-LABEL: f1: ; CHECK: adds {{r.*}}, #187 %tmp = icmp ne i32 %a, 4294967109 - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; -0x00aa00aa = 4283826006 -define i1 @f2(i32 %a) { +define i32 @f2(i32 %a) { ; CHECK-LABEL: f2: ; CHECK: cmn.w {{r.*}}, #11141290 %tmp = icmp eq i32 %a, 4283826006 - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; -0xcc00cc00 = 872363008 -define i1 @f3(i32 %a) { +define i32 @f3(i32 %a) { ; CHECK-LABEL: f3: ; CHECK: cmn.w {{r.*}}, #-872363008 %tmp = icmp ne i32 %a, 872363008 - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; -0x00110000 = 4293853184 -define i1 @f4(i32 %a) { +define i32 @f4(i32 %a) { ; CHECK-LABEL: f4: ; CHECK: cmn.w {{r.*}}, #1114112 %tmp = icmp eq i32 %a, 4293853184 - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } Index: test/CodeGen/Thumb2/thumb2-cmp.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-cmp.ll +++ test/CodeGen/Thumb2/thumb2-cmp.ll @@ -4,43 +4,48 @@ ; test as 'mov.w r0, #0'. ; 0x000000bb = 187 -define i1 @f1(i32 %a) { +define i32 @f1(i32 %a) { ; CHECK-LABEL: f1: ; CHECK: cmp {{.*}}, #187 %tmp = icmp ne i32 %a, 187 - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; 0x00aa00aa = 11141290 -define i1 @f2(i32 %a) { +define i32 @f2(i32 %a) { ; CHECK-LABEL: f2: ; CHECK: cmp.w {{.*}}, #11141290 %tmp = icmp eq i32 %a, 11141290 - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; 0xcc00cc00 = 3422604288 -define i1 @f3(i32 %a) { +define i32 @f3(i32 %a) { ; CHECK-LABEL: f3: ; CHECK: cmp.w {{.*}}, #-872363008 %tmp = icmp ne i32 %a, 3422604288 - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; 0xdddddddd = 3722304989 -define i1 @f4(i32 %a) { +define i32 @f4(i32 %a) { ; CHECK-LABEL: f4: ; CHECK: cmp.w {{.*}}, #-572662307 %tmp = icmp ne i32 %a, 3722304989 - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; 0x00110000 = 1114112 -define i1 @f5(i32 %a) { +define i32 @f5(i32 %a) { ; CHECK-LABEL: f5: ; CHECK: cmp.w {{.*}}, #1114112 %tmp = icmp eq i32 %a, 1114112 - ret i1 %tmp + %ret = select i1 %tmp, i32 42, i32 24 + ret i32 %ret } ; Check that we don't do an invalid (a > b) --> !(a < b + 1) transform. Index: test/CodeGen/Thumb2/thumb2-teq.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-teq.ll +++ test/CodeGen/Thumb2/thumb2-teq.ll @@ -4,54 +4,64 @@ ; test as 'mov.w r0, #0'. ; 0x000000bb = 187 -define i1 @f2(i32 %a) { +define i32 @f2(i32 %a) { %tmp = xor i32 %a, 187 %tmp1 = icmp eq i32 0, %tmp - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f2: ; CHECK: teq.w {{.*}}, #187 ; 0x00aa00aa = 11141290 -define i1 @f3(i32 %a) { +define i32 @f3(i32 %a) { %tmp = xor i32 %a, 11141290 %tmp1 = icmp eq i32 %tmp, 0 - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f3: ; CHECK: teq.w {{.*}}, #11141290 ; 0xcc00cc00 = 3422604288 -define i1 @f6(i32 %a) { +define i32 @f6(i32 %a) { %tmp = xor i32 %a, 3422604288 %tmp1 = icmp eq i32 0, %tmp - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f6: ; CHECK: teq.w {{.*}}, #-872363008 ; 0xdddddddd = 3722304989 -define i1 @f7(i32 %a) { +define i32 @f7(i32 %a) { %tmp = xor i32 %a, 3722304989 %tmp1 = icmp eq i32 %tmp, 0 - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f7: ; CHECK: teq.w {{.*}}, #-572662307 ; 0xdddddddd = 3722304989 -define i1 @f8(i32 %a) { +define i1 @f17(i32 %a) { %tmp = xor i32 %a, 3722304989 - %tmp1 = icmp ne i32 0, %tmp + %tmp1 = icmp eq i32 %tmp, 0 ret i1 %tmp1 } +; CHECK-LABEL: f17: +; CHECK: eor r0, r0, #-572662307 +; CHECK-NEXT: clz r0, r0 +; CHECK-NEXT: lsrs r0, r0, #5 ; 0x00110000 = 1114112 -define i1 @f10(i32 %a) { +define i1 @f18(i32 %a) { %tmp = xor i32 %a, 1114112 %tmp1 = icmp eq i32 0, %tmp ret i1 %tmp1 } -; CHECK-LABEL: f10: -; CHECK: teq.w {{.*}}, #1114112 +; CHECK-LABEL: f18: +; CHECK: eor r0, r0, #1114112 +; CHECK-NEXT: clz r0, r0 +; CHECK-NEXT: lsrs r0, r0, #5 Index: test/CodeGen/Thumb2/thumb2-teq2.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-teq2.ll +++ test/CodeGen/Thumb2/thumb2-teq2.ll @@ -3,50 +3,55 @@ ; These tests would be improved by 'movs r0, #0' being rematerialized below the ; tst as 'mov.w r0, #0'. -define i1 @f2(i32 %a, i32 %b) { +define i32 @f2(i32 %a, i32 %b) { ; CHECK: f2 ; CHECK: teq.w {{.*}}, r1 %tmp = xor i32 %a, %b %tmp1 = icmp eq i32 %tmp, 0 - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } -define i1 @f4(i32 %a, i32 %b) { +define i32 @f4(i32 %a, i32 %b) { ; CHECK: f4 ; CHECK: teq.w {{.*}}, r1 %tmp = xor i32 %a, %b %tmp1 = icmp eq i32 0, %tmp - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } -define i1 @f6(i32 %a, i32 %b) { +define i32 @f6(i32 %a, i32 %b) { ; CHECK: f6 ; CHECK: teq.w {{.*}}, r1, lsl #5 %tmp = shl i32 %b, 5 %tmp1 = xor i32 %a, %tmp %tmp2 = icmp eq i32 %tmp1, 0 - ret i1 %tmp2 + %ret = select i1 %tmp2, i32 42, i32 24 + ret i32 %ret } -define i1 @f7(i32 %a, i32 %b) { +define i32 @f7(i32 %a, i32 %b) { ; CHECK: f7 ; CHECK: teq.w {{.*}}, r1, lsr #6 %tmp = lshr i32 %b, 6 %tmp1 = xor i32 %a, %tmp %tmp2 = icmp eq i32 %tmp1, 0 - ret i1 %tmp2 + %ret = select i1 %tmp2, i32 42, i32 24 + ret i32 %ret } -define i1 @f8(i32 %a, i32 %b) { +define i32 @f8(i32 %a, i32 %b) { ; CHECK: f8 ; CHECK: teq.w {{.*}}, r1, asr #7 %tmp = ashr i32 %b, 7 %tmp1 = xor i32 %a, %tmp %tmp2 = icmp eq i32 %tmp1, 0 - ret i1 %tmp2 + %ret = select i1 %tmp2, i32 42, i32 24 + ret i32 %ret } -define i1 @f9(i32 %a, i32 %b) { +define i32 @f9(i32 %a, i32 %b) { ; CHECK: f9 ; CHECK: teq.w {{.*}}, {{.*}}, ror #8 %l8 = shl i32 %a, 24 @@ -54,5 +59,6 @@ %tmp = or i32 %l8, %r8 %tmp1 = xor i32 %a, %tmp %tmp2 = icmp eq i32 %tmp1, 0 - ret i1 %tmp2 + %ret = select i1 %tmp2, i32 42, i32 24 + ret i32 %ret } Index: test/CodeGen/Thumb2/thumb2-tst.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-tst.ll +++ test/CodeGen/Thumb2/thumb2-tst.ll @@ -4,46 +4,51 @@ ; tst as 'mov.w r0, #0'. ; 0x000000bb = 187 -define i1 @f2(i32 %a) { +define i32 @f2(i32 %a) { %tmp = and i32 %a, 187 %tmp1 = icmp eq i32 0, %tmp - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f2: ; CHECK: tst.w {{.*}}, #187 ; 0x00aa00aa = 11141290 -define i1 @f3(i32 %a) { +define i32 @f3(i32 %a) { %tmp = and i32 %a, 11141290 %tmp1 = icmp eq i32 %tmp, 0 - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f3: ; CHECK: tst.w {{.*}}, #11141290 ; 0xcc00cc00 = 3422604288 -define i1 @f6(i32 %a) { +define i32 @f6(i32 %a) { %tmp = and i32 %a, 3422604288 %tmp1 = icmp eq i32 0, %tmp - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f6: ; CHECK: tst.w {{.*}}, #-872363008 ; 0xdddddddd = 3722304989 -define i1 @f7(i32 %a) { +define i32 @f7(i32 %a) { %tmp = and i32 %a, 3722304989 %tmp1 = icmp eq i32 %tmp, 0 - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f7: ; CHECK: tst.w {{.*}}, #-572662307 ; 0x00110000 = 1114112 -define i1 @f10(i32 %a) { +define i32 @f10(i32 %a) { %tmp = and i32 %a, 1114112 %tmp1 = icmp eq i32 0, %tmp - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } ; CHECK-LABEL: f10: ; CHECK: tst.w {{.*}}, #1114112 Index: test/CodeGen/Thumb2/thumb2-tst2.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-tst2.ll +++ test/CodeGen/Thumb2/thumb2-tst2.ll @@ -3,50 +3,55 @@ ; These tests would be improved by 'movs r0, #0' being rematerialized below the ; tst as 'mov.w r0, #0'. -define i1 @f2(i32 %a, i32 %b) { +define i32 @f2(i32 %a, i32 %b) { ; CHECK-LABEL: f2: ; CHECK: tst {{.*}}, r1 %tmp = and i32 %a, %b %tmp1 = icmp eq i32 %tmp, 0 - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } -define i1 @f4(i32 %a, i32 %b) { +define i32 @f4(i32 %a, i32 %b) { ; CHECK-LABEL: f4: ; CHECK: tst {{.*}}, r1 %tmp = and i32 %a, %b %tmp1 = icmp eq i32 0, %tmp - ret i1 %tmp1 + %ret = select i1 %tmp1, i32 42, i32 24 + ret i32 %ret } -define i1 @f6(i32 %a, i32 %b) { +define i32 @f6(i32 %a, i32 %b) { ; CHECK-LABEL: f6: ; CHECK: tst.w {{.*}}, r1, lsl #5 %tmp = shl i32 %b, 5 %tmp1 = and i32 %a, %tmp %tmp2 = icmp eq i32 %tmp1, 0 - ret i1 %tmp2 + %ret = select i1 %tmp2, i32 42, i32 24 + ret i32 %ret } -define i1 @f7(i32 %a, i32 %b) { +define i32 @f7(i32 %a, i32 %b) { ; CHECK-LABEL: f7: ; CHECK: tst.w {{.*}}, r1, lsr #6 %tmp = lshr i32 %b, 6 %tmp1 = and i32 %a, %tmp %tmp2 = icmp eq i32 %tmp1, 0 - ret i1 %tmp2 + %ret = select i1 %tmp2, i32 42, i32 24 + ret i32 %ret } -define i1 @f8(i32 %a, i32 %b) { +define i32 @f8(i32 %a, i32 %b) { ; CHECK-LABEL: f8: ; CHECK: tst.w {{.*}}, r1, asr #7 %tmp = ashr i32 %b, 7 %tmp1 = and i32 %a, %tmp %tmp2 = icmp eq i32 %tmp1, 0 - ret i1 %tmp2 + %ret = select i1 %tmp2, i32 42, i32 24 + ret i32 %ret } -define i1 @f9(i32 %a, i32 %b) { +define i32 @f9(i32 %a, i32 %b) { ; CHECK-LABEL: f9: ; CHECK: tst.w {{.*}}, {{.*}}, ror #8 %l8 = shl i32 %a, 24 @@ -54,5 +59,6 @@ %tmp = or i32 %l8, %r8 %tmp1 = and i32 %a, %tmp %tmp2 = icmp eq i32 %tmp1, 0 - ret i1 %tmp2 + %ret = select i1 %tmp2, i32 42, i32 24 + ret i32 %ret }