Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -13147,6 +13147,13 @@ SDValue RHS = Op->getOperand(1); SetCCInfoAndKind InfoAndKind; + // If both operands are a SET_CC, then we don't want to perform this + // folding and create another csel as this results in more instructions + // (and higher register usage). + if (isSetCCOrZExtSetCC(LHS, InfoAndKind) && + isSetCCOrZExtSetCC(RHS, InfoAndKind)) + return SDValue(); + // If neither operand is a SET_CC, give up. if (!isSetCCOrZExtSetCC(LHS, InfoAndKind)) { std::swap(LHS, RHS); Index: llvm/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2157,6 +2157,11 @@ def : Pat<(AArch64csel (i64 -1), GPR64:$fval, (i32 imm:$cc), NZCV), (CSINVXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>; +def : Pat<(add GPR32:$val, (AArch64csel (i32 0), (i32 1), (i32 imm:$cc), NZCV)), + (CSINCWr GPR32:$val, GPR32:$val, (i32 imm:$cc))>; +def : Pat<(add GPR64:$val, (zext (AArch64csel (i32 0), (i32 1), (i32 imm:$cc), NZCV))), + (CSINCXr GPR64:$val, GPR64:$val, (i32 imm:$cc))>; + // The inverse of the condition code from the alias instruction is what is used // in the aliased instruction. The parser all ready inverts the condition code // for these aliases. Index: llvm/test/CodeGen/AArch64/arm64-csel.ll =================================================================== --- llvm/test/CodeGen/AArch64/arm64-csel.ll +++ llvm/test/CodeGen/AArch64/arm64-csel.ll @@ -272,14 +272,12 @@ define i16 @foo24(i8* nocapture readonly %A, i8* nocapture readonly %B) { ; CHECK-LABEL: foo24: -; CHECK: ldrb w[[W8:[0-9]+]], [x0] -; CHECK-NEXT: ldrb w[[W9:[0-9]+]], [x1] -; CHECK-NEXT: mov w[[W10:[0-9]+]], #2 -; CHECK-NEXT: cmp w[[W8]], #3 +; CHECK: ldrb w[[W8:[0-9]+]], [x1] +; CHECK-NEXT: ldrb w[[W9:[0-9]+]], [x0] +; CHECK-NEXT: cmp w[[W8]], #33 ; CHECK-NEXT: cset w[[W8]], hi -; CHECK-NEXT: csinc w[[W10]], w[[W10]], wzr, hi -; CHECK-NEXT: cmp w[[W9]], #33 -; CHECK-NEXT: csel w0, w[[W8]], w[[W10]], ls +; CHECK-NEXT: cmp w[[W9]], #3 +; CHECK-NEXT: cinc w0, w[[W8]], hi ; CHECK-NEXT: ret entry: %0 = load i8, i8* %A, align 1 @@ -291,3 +289,24 @@ %add = add nuw nsw i16 %conv5, %conv1 ret i16 %add } + +define i64 @foo25(i64* nocapture readonly %A, i64* nocapture readonly %B) { +; CHECK-LABEL: foo25: +; CHECK: ldr x[[X8:[0-9]+]], [x1] +; CHECK-NEXT: ldr x[[X9:[0-9]+]], [x0] +; CHECK-NEXT: cmp x[[X8]], #33 +; CHECK-NEXT: cset w[[W8]], hi +; CHECK-NEXT: cmp x[[X9]], #3 +; CHECK-NEXT: cinc x0, x[[X8]], hi +; CHECK-NEXT: ret +entry: + %0 = load i64, i64* %A, align 1 + %cmp = icmp ugt i64 %0, 3 + %conv1 = zext i1 %cmp to i64 + %1 = load i64, i64* %B, align 1 + %cmp4 = icmp ugt i64 %1, 33 + %conv5 = zext i1 %cmp4 to i64 + %add = add nuw nsw i64 %conv5, %conv1 + ret i64 %add +} +