diff --git a/llvm/test/CodeGen/AArch64/cmp-chains.ll b/llvm/test/CodeGen/AArch64/cmp-chains.ll index 14cb0c82b1c039..3ee6e8f55044e2 100644 --- a/llvm/test/CodeGen/AArch64/cmp-chains.ll +++ b/llvm/test/CodeGen/AArch64/cmp-chains.ll @@ -258,3 +258,191 @@ define i32 @neg_range_int(i32 %a, i32 %b, i32 %c) { ret i32 %retval.0 } +; (b > -(d | 1) && a < c) +define i32 @neg_range_int_comp(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: neg_range_int_comp: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w3, #0x1 +; CHECK-NEXT: cmp w0, w2 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: ccmp w1, w8, #4, lt +; CHECK-NEXT: csel w0, w1, w0, gt +; CHECK-NEXT: ret + %dor = or i32 %d, 1 + %negd = sub i32 0, %dor + %cmp = icmp sgt i32 %b, %negd + %cmp1 = icmp slt i32 %a, %c + %or.cond = and i1 %cmp, %cmp1 + %retval.0 = select i1 %or.cond, i32 %b, i32 %a + ret i32 %retval.0 +} + +; (b >u -(d | 1) && a < c) +define i32 @neg_range_int_comp_u(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: neg_range_int_comp_u: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w3, #0x1 +; CHECK-NEXT: cmp w0, w2 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: ccmp w1, w8, #0, lt +; CHECK-NEXT: csel w0, w1, w0, hi +; CHECK-NEXT: ret + %dor = or i32 %d, 1 + %negd = sub i32 0, %dor + %cmp = icmp ugt i32 %b, %negd + %cmp1 = icmp slt i32 %a, %c + %or.cond = and i1 %cmp, %cmp1 + %retval.0 = select i1 %or.cond, i32 %b, i32 %a + ret i32 %retval.0 +} + +; (b > -(d | 1) && a u < c) +define i32 @neg_range_int_comp_ua(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: neg_range_int_comp_ua: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w3, #0x1 +; CHECK-NEXT: cmp w0, w2 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: ccmp w1, w8, #4, lo +; CHECK-NEXT: csel w0, w1, w0, gt +; CHECK-NEXT: ret + %dor = or i32 %d, 1 + %negd = sub i32 0, %dor + %cmp = icmp sgt i32 %b, %negd + %cmp1 = icmp ult i32 %a, %c + %or.cond = and i1 %cmp, %cmp1 + %retval.0 = select i1 %or.cond, i32 %b, i32 %a + ret i32 %retval.0 +} + +; (b <= -3 && a > c) +define i32 @neg_range_int_2(i32 %a, i32 %b, i32 %c) { +; SDISEL-LABEL: neg_range_int_2: +; SDISEL: // %bb.0: +; SDISEL-NEXT: cmp w0, w2 +; SDISEL-NEXT: ccmn w1, #4, #4, gt +; SDISEL-NEXT: csel w0, w1, w0, gt +; SDISEL-NEXT: ret +; +; GISEL-LABEL: neg_range_int_2: +; GISEL: // %bb.0: +; GISEL-NEXT: cmp w0, w2 +; GISEL-NEXT: ccmn w1, #3, #8, gt +; GISEL-NEXT: csel w0, w1, w0, ge +; GISEL-NEXT: ret + %cmp = icmp sge i32 %b, -3 + %cmp1 = icmp sgt i32 %a, %c + %or.cond = and i1 %cmp, %cmp1 + %retval.0 = select i1 %or.cond, i32 %b, i32 %a + ret i32 %retval.0 +} + +; (b < -(d | 1) && a >= c) +define i32 @neg_range_int_comp2(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: neg_range_int_comp2: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w3, #0x1 +; CHECK-NEXT: cmp w0, w2 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: ccmp w1, w8, #0, ge +; CHECK-NEXT: csel w0, w1, w0, lt +; CHECK-NEXT: ret + %dor = or i32 %d, 1 + %negd = sub i32 0, %dor + %cmp = icmp slt i32 %b, %negd + %cmp1 = icmp sge i32 %a, %c + %or.cond = and i1 %cmp, %cmp1 + %retval.0 = select i1 %or.cond, i32 %b, i32 %a + ret i32 %retval.0 +} + +; (b c) +define i32 @neg_range_int_comp_u2(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: neg_range_int_comp_u2: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w3, #0x1 +; CHECK-NEXT: cmp w0, w2 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: ccmp w1, w8, #2, gt +; CHECK-NEXT: csel w0, w1, w0, lo +; CHECK-NEXT: ret + %dor = or i32 %d, 1 + %negd = sub i32 0, %dor + %cmp = icmp ult i32 %b, %negd + %cmp1 = icmp sgt i32 %a, %c + %or.cond = and i1 %cmp, %cmp1 + %retval.0 = select i1 %or.cond, i32 %b, i32 %a + ret i32 %retval.0 +} + +; (b > -(d | 1) && a u > c) +define i32 @neg_range_int_comp_ua2(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: neg_range_int_comp_ua2: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w3, #0x1 +; CHECK-NEXT: cmp w0, w2 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: ccmp w1, w8, #4, hi +; CHECK-NEXT: csel w0, w1, w0, gt +; CHECK-NEXT: ret + %dor = or i32 %d, 1 + %negd = sub i32 0, %dor + %cmp = icmp sgt i32 %b, %negd + %cmp1 = icmp ugt i32 %a, %c + %or.cond = and i1 %cmp, %cmp1 + %retval.0 = select i1 %or.cond, i32 %b, i32 %a + ret i32 %retval.0 +} + +; (b > -(d | 1) && a u == c) +define i32 @neg_range_int_comp_ua3(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: neg_range_int_comp_ua3: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w3, #0x1 +; CHECK-NEXT: cmp w0, w2 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: ccmp w1, w8, #4, eq +; CHECK-NEXT: csel w0, w1, w0, gt +; CHECK-NEXT: ret + %dor = or i32 %d, 1 + %negd = sub i32 0, %dor + %cmp = icmp sgt i32 %b, %negd + %cmp1 = icmp eq i32 %a, %c + %or.cond = and i1 %cmp, %cmp1 + %retval.0 = select i1 %or.cond, i32 %b, i32 %a + ret i32 %retval.0 +} + +; -(a | 1) > (b | 3) && a < c +define i32 @neg_range_int_c(i32 %a, i32 %b, i32 %c) { +; SDISEL-LABEL: neg_range_int_c: +; SDISEL: // %bb.0: // %entry +; SDISEL-NEXT: orr w8, w0, #0x1 +; SDISEL-NEXT: orr w9, w1, #0x3 +; SDISEL-NEXT: neg w8, w8 +; SDISEL-NEXT: cmp w9, w8 +; SDISEL-NEXT: ccmp w2, w0, #2, lo +; SDISEL-NEXT: cset w0, lo +; SDISEL-NEXT: ret +; +; GISEL-LABEL: neg_range_int_c: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: orr w8, w0, #0x1 +; GISEL-NEXT: orr w9, w1, #0x3 +; GISEL-NEXT: neg w8, w8 +; GISEL-NEXT: cmp w9, w8 +; GISEL-NEXT: cset w8, lo +; GISEL-NEXT: cmp w2, w0 +; GISEL-NEXT: cset w9, lo +; GISEL-NEXT: and w0, w8, w9 +; GISEL-NEXT: ret +entry: + %or = or i32 %a, 1 + %sub = sub i32 0, %or + %or1 = or i32 %b, 3 + %cmp = icmp ult i32 %or1, %sub + %cmp2 = icmp ult i32 %c, %a + %0 = and i1 %cmp, %cmp2 + %land.ext = zext i1 %0 to i32 + ret i32 %land.ext +} diff --git a/llvm/test/CodeGen/AArch64/cmp-select-sign.ll b/llvm/test/CodeGen/AArch64/cmp-select-sign.ll index 09a6e26fe5a403..a16528ef871a45 100644 --- a/llvm/test/CodeGen/AArch64/cmp-select-sign.ll +++ b/llvm/test/CodeGen/AArch64/cmp-select-sign.ll @@ -262,4 +262,218 @@ define <4 x i65> @sign_4xi65(<4 x i65> %a) { ret <4 x i65> %res } +define i32 @or_neg(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w0, #0x1 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, gt +; CHECK-NEXT: ret + %3 = or i32 %x, 1 + %4 = sub i32 0, %3 + %5 = icmp sgt i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg_ugt(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_ugt: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w0, #0x1 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %3 = or i32 %x, 1 + %4 = sub i32 0, %3 + %5 = icmp ugt i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +; Negative test + +define i32 @or_neg_no_smin(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_no_smin: +; CHECK: // %bb.0: +; CHECK-NEXT: neg w8, w0 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, gt +; CHECK-NEXT: ret + %4 = sub i32 0, %x + %5 = icmp sgt i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +; Negative test + +define i32 @or_neg_ult_no_zero(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_ult_no_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: neg w8, w0 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %4 = sub i32 0, %x + %5 = icmp ult i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg_no_smin_but_zero(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_no_smin_but_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: bic w8, w0, w0, asr #31 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, gt +; CHECK-NEXT: ret + %3 = call i32 @llvm.smax.i32(i32 %x, i32 0) + %4 = sub i32 0, %3 + %5 = icmp sgt i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg_slt_zero_but_no_smin(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_slt_zero_but_no_smin: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #9 // =0x9 +; CHECK-NEXT: cmp w0, #9 +; CHECK-NEXT: csel w8, w0, w8, lo +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %3 = call i32 @llvm.umin.i32(i32 %x, i32 9) + %4 = sub i32 0, %3 + %5 = icmp ugt i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg2(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg2: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w0, #0x1 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, ge +; CHECK-NEXT: ret + %3 = or i32 %x, 1 + %4 = sub i32 0, %3 + %5 = icmp sge i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg3(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg3: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w0, #0x1 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, lt +; CHECK-NEXT: ret + %3 = or i32 %x, 1 + %4 = sub i32 0, %3 + %5 = icmp slt i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg4(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg4: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w0, #0x1 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, le +; CHECK-NEXT: ret + %3 = or i32 %x, 1 + %4 = sub i32 0, %3 + %5 = icmp sle i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg_ult(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: orr w8, w0, #0x1 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %3 = or i32 %x, 1 + %4 = sub i32 0, %3 + %5 = icmp ugt i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg_no_smin2(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_no_smin2: +; CHECK: // %bb.0: +; CHECK-NEXT: neg w8, w0 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, ge +; CHECK-NEXT: ret + %4 = sub i32 0, %x + %5 = icmp sge i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +; Negative test + +define i32 @or_neg_ult_no_zero2(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_ult_no_zero2: +; CHECK: // %bb.0: +; CHECK-NEXT: neg w8, w0 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %4 = sub i32 0, %x + %5 = icmp ult i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg_no_smin_but_zero2(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_no_smin_but_zero2: +; CHECK: // %bb.0: +; CHECK-NEXT: bic w8, w0, w0, asr #31 +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, le +; CHECK-NEXT: ret + %3 = call i32 @llvm.smax.i32(i32 %x, i32 0) + %4 = sub i32 0, %3 + %5 = icmp sle i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +define i32 @or_neg_slt_zero_but_no_smin2(i32 %x, i32 %y) { +; CHECK-LABEL: or_neg_slt_zero_but_no_smin2: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #9 // =0x9 +; CHECK-NEXT: cmp w0, #9 +; CHECK-NEXT: csel w8, w0, w8, lo +; CHECK-NEXT: neg w8, w8 +; CHECK-NEXT: cmp w8, w1 +; CHECK-NEXT: cset w0, hs +; CHECK-NEXT: ret + %3 = call i32 @llvm.umin.i32(i32 %x, i32 9) + %4 = sub i32 0, %3 + %5 = icmp uge i32 %4, %y + %6 = zext i1 %5 to i32 + ret i32 %6 +} + +declare i32 @llvm.smax.i32(i32, i32) +declare i32 @llvm.umax.i32(i32, i32) declare void @use_4xi1(<4 x i1>)