Skip to content

Commit 1a60ae0

Browse files
committed
[InstCombine] fold mask-with-signbit-splat to icmp+select
~(iN X s>> (N-1)) & Y --> (X s< 0) ? 0 : Y https://alive2.llvm.org/ce/z/JKlQ9x This is similar to D111410 / 727e642 , but it includes a 'not' of the signbit and so it saves an instruction in the basic pattern. DAGCombiner or target-specific folds can expand this back into bit-hacks. The diffs in the logical-select tests are not true regressions - running early-cse and another round of instcombine is expected in a normal opt pipeline, and that reduces back to a minimal form as shown in the duplicated PhaseOrdering test. I have no understanding of the SystemZ diffs, so I made the minimal edits suggested by FileCheck to make that test pass again. That whole test file is wrong though. It is running the entire optimizer (-O2) to check IR, and then topping that by even running codegen and checking asm. It needs to be split up. Fixes #52631
1 parent 96130b5 commit 1a60ae0

File tree

7 files changed

+69
-43
lines changed

7 files changed

+69
-43
lines changed

clang/test/CodeGen/SystemZ/builtins-systemz-zvector.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3289,13 +3289,13 @@ void test_integer(void) {
32893289
// CHECK-ASM: vsrlb
32903290

32913291
vsc = vec_abs(vsc);
3292-
// CHECK-ASM: vlpb
3292+
// CHECK-ASM: vlcb
32933293
vss = vec_abs(vss);
3294-
// CHECK-ASM: vlph
3294+
// CHECK-ASM: vlch
32953295
vsi = vec_abs(vsi);
3296-
// CHECK-ASM: vlpf
3296+
// CHECK-ASM: vlcf
32973297
vsl = vec_abs(vsl);
3298-
// CHECK-ASM: vlpg
3298+
// CHECK-ASM: vlcg
32993299

33003300
vsc = vec_max(vsc, vsc);
33013301
// CHECK-ASM: vmxb

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,6 +2133,15 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
21332133
Value *Cmp = Builder.CreateICmpSLT(X, Zero, "isneg");
21342134
return SelectInst::Create(Cmp, Y, Zero);
21352135
}
2136+
// If there's a 'not' of the shifted value, swap the select operands:
2137+
// ~(iN X s>> (N-1)) & Y --> (X s< 0) ? 0 : Y
2138+
if (match(&I, m_c_And(m_OneUse(m_Not(
2139+
m_AShr(m_Value(X), m_SpecificInt(FullShift)))),
2140+
m_Value(Y)))) {
2141+
Constant *Zero = ConstantInt::getNullValue(Ty);
2142+
Value *Cmp = Builder.CreateICmpSLT(X, Zero, "isneg");
2143+
return SelectInst::Create(Cmp, Zero, Y);
2144+
}
21362145

21372146
// (~x) & y --> ~(x | (~y)) iff that gets rid of inversions
21382147
if (sinkNotIntoOtherHandOfAndOrOr(I))

llvm/test/Transforms/InstCombine/and.ll

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,9 +1463,8 @@ define i8 @lshr_bitwidth_mask(i8 %x, i8 %y) {
14631463

14641464
define i8 @not_ashr_bitwidth_mask(i8 %x, i8 %y) {
14651465
; CHECK-LABEL: @not_ashr_bitwidth_mask(
1466-
; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 7
1467-
; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[SIGN]], -1
1468-
; CHECK-NEXT: [[POS_OR_ZERO:%.*]] = and i8 [[NOT]], [[Y:%.*]]
1466+
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i8 [[X:%.*]], 0
1467+
; CHECK-NEXT: [[POS_OR_ZERO:%.*]] = select i1 [[ISNEG]], i8 0, i8 [[Y:%.*]]
14691468
; CHECK-NEXT: ret i8 [[POS_OR_ZERO]]
14701469
;
14711470
%sign = ashr i8 %x, 7
@@ -1477,9 +1476,8 @@ define i8 @not_ashr_bitwidth_mask(i8 %x, i8 %y) {
14771476
define <2 x i8> @not_ashr_bitwidth_mask_vec_commute(<2 x i8> %x, <2 x i8> %py) {
14781477
; CHECK-LABEL: @not_ashr_bitwidth_mask_vec_commute(
14791478
; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], <i8 42, i8 2>
1480-
; CHECK-NEXT: [[SIGN:%.*]] = ashr <2 x i8> [[X:%.*]], <i8 7, i8 7>
1481-
; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i8> [[SIGN]], <i8 -1, i8 -1>
1482-
; CHECK-NEXT: [[POS_OR_ZERO:%.*]] = and <2 x i8> [[Y]], [[NOT]]
1479+
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
1480+
; CHECK-NEXT: [[POS_OR_ZERO:%.*]] = select <2 x i1> [[ISNEG]], <2 x i8> zeroinitializer, <2 x i8> [[Y]]
14831481
; CHECK-NEXT: ret <2 x i8> [[POS_OR_ZERO]]
14841482
;
14851483
%y = mul <2 x i8> %py, <i8 42, i8 2> ; thwart complexity-based ordering
@@ -1489,12 +1487,14 @@ define <2 x i8> @not_ashr_bitwidth_mask_vec_commute(<2 x i8> %x, <2 x i8> %py) {
14891487
ret <2 x i8> %pos_or_zero
14901488
}
14911489

1490+
; extra use of shift is ok
1491+
14921492
define i8 @not_ashr_bitwidth_mask_use1(i8 %x, i8 %y) {
14931493
; CHECK-LABEL: @not_ashr_bitwidth_mask_use1(
14941494
; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 7
14951495
; CHECK-NEXT: call void @use8(i8 [[SIGN]])
1496-
; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[SIGN]], -1
1497-
; CHECK-NEXT: [[R:%.*]] = and i8 [[NOT]], [[Y:%.*]]
1496+
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i8 [[X]], 0
1497+
; CHECK-NEXT: [[R:%.*]] = select i1 [[ISNEG]], i8 0, i8 [[Y:%.*]]
14981498
; CHECK-NEXT: ret i8 [[R]]
14991499
;
15001500
%sign = ashr i8 %x, 7
@@ -1504,6 +1504,8 @@ define i8 @not_ashr_bitwidth_mask_use1(i8 %x, i8 %y) {
15041504
ret i8 %r
15051505
}
15061506

1507+
; negative test - extra use
1508+
15071509
define i8 @not_ashr_bitwidth_mask_use2(i8 %x, i8 %y) {
15081510
; CHECK-LABEL: @not_ashr_bitwidth_mask_use2(
15091511
; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 7
@@ -1519,6 +1521,8 @@ define i8 @not_ashr_bitwidth_mask_use2(i8 %x, i8 %y) {
15191521
ret i8 %r
15201522
}
15211523

1524+
; negative test - wrong shift amount
1525+
15221526
define i8 @not_ashr_not_bitwidth_mask(i8 %x, i8 %y) {
15231527
; CHECK-LABEL: @not_ashr_not_bitwidth_mask(
15241528
; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 6
@@ -1532,6 +1536,8 @@ define i8 @not_ashr_not_bitwidth_mask(i8 %x, i8 %y) {
15321536
ret i8 %r
15331537
}
15341538

1539+
; negative test - wrong shift opcode
1540+
15351541
define i8 @not_lshr_bitwidth_mask(i8 %x, i8 %y) {
15361542
; CHECK-LABEL: @not_lshr_bitwidth_mask(
15371543
; CHECK-NEXT: [[SIGN:%.*]] = lshr i8 [[X:%.*]], 7

llvm/test/Transforms/InstCombine/logical-select-inseltpoison.ll

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -582,9 +582,12 @@ define <4 x i32> @vec_sel_xor_multi_use(<4 x i32> %a, <4 x i32> %b, <4 x i1> %c)
582582

583583
define i32 @allSignBits(i32 %cond, i32 %tval, i32 %fval) {
584584
; CHECK-LABEL: @allSignBits(
585-
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp sgt i32 [[COND:%.*]], -1
586-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTNOT]], i32 [[FVAL:%.*]], i32 [[TVAL:%.*]]
587-
; CHECK-NEXT: ret i32 [[TMP1]]
585+
; CHECK-NEXT: [[ISNEG1:%.*]] = icmp slt i32 [[COND:%.*]], 0
586+
; CHECK-NEXT: [[A1:%.*]] = select i1 [[ISNEG1]], i32 [[TVAL:%.*]], i32 0
587+
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[COND]], 0
588+
; CHECK-NEXT: [[A2:%.*]] = select i1 [[ISNEG]], i32 0, i32 [[FVAL:%.*]]
589+
; CHECK-NEXT: [[SEL:%.*]] = or i32 [[A1]], [[A2]]
590+
; CHECK-NEXT: ret i32 [[SEL]]
588591
;
589592
%bitmask = ashr i32 %cond, 31
590593
%not_bitmask = xor i32 %bitmask, -1
@@ -596,9 +599,12 @@ define i32 @allSignBits(i32 %cond, i32 %tval, i32 %fval) {
596599

597600
define <4 x i8> @allSignBits_vec(<4 x i8> %cond, <4 x i8> %tval, <4 x i8> %fval) {
598601
; CHECK-LABEL: @allSignBits_vec(
599-
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp sgt <4 x i8> [[COND:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
600-
; CHECK-NEXT: [[TMP1:%.*]] = select <4 x i1> [[DOTNOT]], <4 x i8> [[FVAL:%.*]], <4 x i8> [[TVAL:%.*]]
601-
; CHECK-NEXT: ret <4 x i8> [[TMP1]]
602+
; CHECK-NEXT: [[ISNEG1:%.*]] = icmp slt <4 x i8> [[COND:%.*]], zeroinitializer
603+
; CHECK-NEXT: [[A1:%.*]] = select <4 x i1> [[ISNEG1]], <4 x i8> [[TVAL:%.*]], <4 x i8> zeroinitializer
604+
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <4 x i8> [[COND]], zeroinitializer
605+
; CHECK-NEXT: [[A2:%.*]] = select <4 x i1> [[ISNEG]], <4 x i8> zeroinitializer, <4 x i8> [[FVAL:%.*]]
606+
; CHECK-NEXT: [[SEL:%.*]] = or <4 x i8> [[A2]], [[A1]]
607+
; CHECK-NEXT: ret <4 x i8> [[SEL]]
602608
;
603609
%bitmask = ashr <4 x i8> %cond, <i8 7, i8 7, i8 7, i8 7>
604610
%not_bitmask = xor <4 x i8> %bitmask, <i8 -1, i8 -1, i8 -1, i8 -1>

llvm/test/Transforms/InstCombine/logical-select.ll

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -583,9 +583,12 @@ define <4 x i32> @vec_sel_xor_multi_use(<4 x i32> %a, <4 x i32> %b, <4 x i1> %c)
583583

584584
define i32 @allSignBits(i32 %cond, i32 %tval, i32 %fval) {
585585
; CHECK-LABEL: @allSignBits(
586-
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp sgt i32 [[COND:%.*]], -1
587-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTNOT]], i32 [[FVAL:%.*]], i32 [[TVAL:%.*]]
588-
; CHECK-NEXT: ret i32 [[TMP1]]
586+
; CHECK-NEXT: [[ISNEG1:%.*]] = icmp slt i32 [[COND:%.*]], 0
587+
; CHECK-NEXT: [[A1:%.*]] = select i1 [[ISNEG1]], i32 [[TVAL:%.*]], i32 0
588+
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[COND]], 0
589+
; CHECK-NEXT: [[A2:%.*]] = select i1 [[ISNEG]], i32 0, i32 [[FVAL:%.*]]
590+
; CHECK-NEXT: [[SEL:%.*]] = or i32 [[A1]], [[A2]]
591+
; CHECK-NEXT: ret i32 [[SEL]]
589592
;
590593
%bitmask = ashr i32 %cond, 31
591594
%not_bitmask = xor i32 %bitmask, -1
@@ -597,9 +600,12 @@ define i32 @allSignBits(i32 %cond, i32 %tval, i32 %fval) {
597600

598601
define <4 x i8> @allSignBits_vec(<4 x i8> %cond, <4 x i8> %tval, <4 x i8> %fval) {
599602
; CHECK-LABEL: @allSignBits_vec(
600-
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp sgt <4 x i8> [[COND:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
601-
; CHECK-NEXT: [[TMP1:%.*]] = select <4 x i1> [[DOTNOT]], <4 x i8> [[FVAL:%.*]], <4 x i8> [[TVAL:%.*]]
602-
; CHECK-NEXT: ret <4 x i8> [[TMP1]]
603+
; CHECK-NEXT: [[ISNEG1:%.*]] = icmp slt <4 x i8> [[COND:%.*]], zeroinitializer
604+
; CHECK-NEXT: [[A1:%.*]] = select <4 x i1> [[ISNEG1]], <4 x i8> [[TVAL:%.*]], <4 x i8> zeroinitializer
605+
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <4 x i8> [[COND]], zeroinitializer
606+
; CHECK-NEXT: [[A2:%.*]] = select <4 x i1> [[ISNEG]], <4 x i8> zeroinitializer, <4 x i8> [[FVAL:%.*]]
607+
; CHECK-NEXT: [[SEL:%.*]] = or <4 x i8> [[A2]], [[A1]]
608+
; CHECK-NEXT: ret <4 x i8> [[SEL]]
603609
;
604610
%bitmask = ashr <4 x i8> %cond, <i8 7, i8 7, i8 7, i8 7>
605611
%not_bitmask = xor <4 x i8> %bitmask, <i8 -1, i8 -1, i8 -1, i8 -1>

llvm/test/Transforms/InstCombine/vec_sext.ll

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
define <4 x i32> @vec_select(<4 x i32> %a, <4 x i32> %b) {
55
; CHECK-LABEL: @vec_select(
66
; CHECK-NEXT: [[SUB:%.*]] = sub nsw <4 x i32> zeroinitializer, [[A:%.*]]
7-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i32> [[B:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
8-
; CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[A]], <4 x i32> [[SUB]]
9-
; CHECK-NEXT: ret <4 x i32> [[TMP2]]
7+
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <4 x i32> [[B:%.*]], zeroinitializer
8+
; CHECK-NEXT: [[T2:%.*]] = select <4 x i1> [[ISNEG]], <4 x i32> zeroinitializer, <4 x i32> [[A]]
9+
; CHECK-NEXT: [[ISNEG1:%.*]] = icmp slt <4 x i32> [[B]], zeroinitializer
10+
; CHECK-NEXT: [[T3:%.*]] = select <4 x i1> [[ISNEG1]], <4 x i32> [[SUB]], <4 x i32> zeroinitializer
11+
; CHECK-NEXT: [[COND:%.*]] = or <4 x i32> [[T2]], [[T3]]
12+
; CHECK-NEXT: ret <4 x i32> [[COND]]
1013
;
1114
%cmp = icmp slt <4 x i32> %b, zeroinitializer
1215
%sext = sext <4 x i1> %cmp to <4 x i32>
@@ -23,9 +26,12 @@ define <4 x i32> @vec_select(<4 x i32> %a, <4 x i32> %b) {
2326
define <4 x i32> @vec_select_alternate_sign_bit_test(<4 x i32> %a, <4 x i32> %b) {
2427
; CHECK-LABEL: @vec_select_alternate_sign_bit_test(
2528
; CHECK-NEXT: [[SUB:%.*]] = sub nsw <4 x i32> zeroinitializer, [[A:%.*]]
26-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i32> [[B:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
27-
; CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[SUB]], <4 x i32> [[A]]
28-
; CHECK-NEXT: ret <4 x i32> [[TMP2]]
29+
; CHECK-NEXT: [[ISNEG1:%.*]] = icmp slt <4 x i32> [[B:%.*]], zeroinitializer
30+
; CHECK-NEXT: [[T2:%.*]] = select <4 x i1> [[ISNEG1]], <4 x i32> [[A]], <4 x i32> zeroinitializer
31+
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <4 x i32> [[B]], zeroinitializer
32+
; CHECK-NEXT: [[T3:%.*]] = select <4 x i1> [[ISNEG]], <4 x i32> zeroinitializer, <4 x i32> [[SUB]]
33+
; CHECK-NEXT: [[COND:%.*]] = or <4 x i32> [[T2]], [[T3]]
34+
; CHECK-NEXT: ret <4 x i32> [[COND]]
2935
;
3036
%cmp = icmp sgt <4 x i32> %b, <i32 -1, i32 -1, i32 -1, i32 -1>
3137
%sext = sext <4 x i1> %cmp to <4 x i32>

llvm/test/Transforms/PhaseOrdering/vector-select.ll

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,9 @@
33

44
define <3 x float> @PR52631(<3 x float> %a, <3 x float> %b, <3 x i32> %c) {
55
; CHECK-LABEL: @PR52631(
6-
; CHECK-NEXT: [[ASTYPE:%.*]] = bitcast <3 x float> [[B:%.*]] to <3 x i32>
7-
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <3 x i32> [[C:%.*]], zeroinitializer
8-
; CHECK-NEXT: [[AND:%.*]] = select <3 x i1> [[ISNEG]], <3 x i32> [[ASTYPE]], <3 x i32> zeroinitializer
9-
; CHECK-NEXT: [[C_LOBIT2:%.*]] = ashr <3 x i32> [[C]], <i32 31, i32 31, i32 31>
10-
; CHECK-NEXT: [[C_LOBIT2_NOT:%.*]] = xor <3 x i32> [[C_LOBIT2]], <i32 -1, i32 -1, i32 -1>
11-
; CHECK-NEXT: [[ASTYPE28:%.*]] = bitcast <3 x float> [[A:%.*]] to <3 x i32>
12-
; CHECK-NEXT: [[AND29:%.*]] = and <3 x i32> [[C_LOBIT2_NOT]], [[ASTYPE28]]
13-
; CHECK-NEXT: [[OR:%.*]] = or <3 x i32> [[AND29]], [[AND]]
14-
; CHECK-NEXT: [[ASTYPE33:%.*]] = bitcast <3 x i32> [[OR]] to <3 x float>
15-
; CHECK-NEXT: ret <3 x float> [[ASTYPE33]]
6+
; CHECK-NEXT: [[ISNEG3:%.*]] = icmp slt <3 x i32> [[C:%.*]], zeroinitializer
7+
; CHECK-NEXT: [[OR_V:%.*]] = select <3 x i1> [[ISNEG3]], <3 x float> [[B:%.*]], <3 x float> [[A:%.*]]
8+
; CHECK-NEXT: ret <3 x float> [[OR_V]]
169
;
1710
%a.addr = alloca <3 x float>, align 16
1811
%b.addr = alloca <3 x float>, align 16
@@ -85,9 +78,9 @@ define <3 x float> @PR52631(<3 x float> %a, <3 x float> %b, <3 x i32> %c) {
8578

8679
define <4 x i8> @allSignBits_vec(<4 x i8> %cond, <4 x i8> %tval, <4 x i8> %fval) {
8780
; CHECK-LABEL: @allSignBits_vec(
88-
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp sgt <4 x i8> [[COND:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
89-
; CHECK-NEXT: [[TMP1:%.*]] = select <4 x i1> [[DOTNOT]], <4 x i8> [[FVAL:%.*]], <4 x i8> [[TVAL:%.*]]
90-
; CHECK-NEXT: ret <4 x i8> [[TMP1]]
81+
; CHECK-NEXT: [[ISNEG1:%.*]] = icmp slt <4 x i8> [[COND:%.*]], zeroinitializer
82+
; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[ISNEG1]], <4 x i8> [[TVAL:%.*]], <4 x i8> [[FVAL:%.*]]
83+
; CHECK-NEXT: ret <4 x i8> [[SEL]]
9184
;
9285
%bitmask = ashr <4 x i8> %cond, <i8 7, i8 7, i8 7, i8 7>
9386
%not_bitmask = xor <4 x i8> %bitmask, <i8 -1, i8 -1, i8 -1, i8 -1>

0 commit comments

Comments
 (0)