Skip to content

Commit 9a3e81e

Browse files
rotaterighttstellar
authored andcommitted
[InstCombine] canonicalize select with signbit test
This is part of solving issue #54750 - in that example we have both forms of the compare and do not recognize the equivalence. (cherry picked from commit 2c2568f)
1 parent b83c4a2 commit 9a3e81e

File tree

4 files changed

+61
-44
lines changed

4 files changed

+61
-44
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,23 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
15721572
}
15731573
}
15741574

1575+
// Canonicalize a signbit condition to use zero constant by swapping:
1576+
// (CmpLHS > -1) ? TV : FV --> (CmpLHS < 0) ? FV : TV
1577+
// To avoid conflicts (infinite loops) with other canonicalizations, this is
1578+
// not applied with any constant select arm.
1579+
if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, m_AllOnes()) &&
1580+
!match(TrueVal, m_Constant()) && !match(FalseVal, m_Constant()) &&
1581+
ICI->hasOneUse()) {
1582+
InstCombiner::BuilderTy::InsertPointGuard Guard(Builder);
1583+
Builder.SetInsertPoint(&SI);
1584+
Value *IsNeg = Builder.CreateICmpSLT(
1585+
CmpLHS, ConstantInt::getNullValue(CmpLHS->getType()), ICI->getName());
1586+
replaceOperand(SI, 0, IsNeg);
1587+
SI.swapValues();
1588+
SI.swapProfMetadata();
1589+
return &SI;
1590+
}
1591+
15751592
// FIXME: This code is nearly duplicated in InstSimplify. Using/refactoring
15761593
// decomposeBitTestICmp() might help.
15771594
{

llvm/test/Transforms/InstCombine/ashr-lshr.ll

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
define i32 @ashr_lshr_exact_ashr_only(i32 %x, i32 %y) {
55
; CHECK-LABEL: @ashr_lshr_exact_ashr_only(
6-
; CHECK-NEXT: [[CMP1:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]]
7-
; CHECK-NEXT: ret i32 [[CMP1]]
6+
; CHECK-NEXT: [[CMP12:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]]
7+
; CHECK-NEXT: ret i32 [[CMP12]]
88
;
99
%cmp = icmp sgt i32 %x, -1
1010
%l = lshr i32 %x, %y
@@ -15,8 +15,8 @@ define i32 @ashr_lshr_exact_ashr_only(i32 %x, i32 %y) {
1515

1616
define i32 @ashr_lshr_no_exact(i32 %x, i32 %y) {
1717
; CHECK-LABEL: @ashr_lshr_no_exact(
18-
; CHECK-NEXT: [[CMP1:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]]
19-
; CHECK-NEXT: ret i32 [[CMP1]]
18+
; CHECK-NEXT: [[CMP12:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]]
19+
; CHECK-NEXT: ret i32 [[CMP12]]
2020
;
2121
%cmp = icmp sgt i32 %x, -1
2222
%l = lshr i32 %x, %y
@@ -27,8 +27,8 @@ define i32 @ashr_lshr_no_exact(i32 %x, i32 %y) {
2727

2828
define i32 @ashr_lshr_exact_both(i32 %x, i32 %y) {
2929
; CHECK-LABEL: @ashr_lshr_exact_both(
30-
; CHECK-NEXT: [[CMP1:%.*]] = ashr exact i32 [[X:%.*]], [[Y:%.*]]
31-
; CHECK-NEXT: ret i32 [[CMP1]]
30+
; CHECK-NEXT: [[CMP12:%.*]] = ashr exact i32 [[X:%.*]], [[Y:%.*]]
31+
; CHECK-NEXT: ret i32 [[CMP12]]
3232
;
3333
%cmp = icmp sgt i32 %x, -1
3434
%l = lshr exact i32 %x, %y
@@ -39,8 +39,8 @@ define i32 @ashr_lshr_exact_both(i32 %x, i32 %y) {
3939

4040
define i32 @ashr_lshr_exact_lshr_only(i32 %x, i32 %y) {
4141
; CHECK-LABEL: @ashr_lshr_exact_lshr_only(
42-
; CHECK-NEXT: [[CMP1:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]]
43-
; CHECK-NEXT: ret i32 [[CMP1]]
42+
; CHECK-NEXT: [[CMP12:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]]
43+
; CHECK-NEXT: ret i32 [[CMP12]]
4444
;
4545
%cmp = icmp sgt i32 %x, -1
4646
%l = lshr exact i32 %x, %y
@@ -63,8 +63,8 @@ define i32 @ashr_lshr2(i32 %x, i32 %y) {
6363

6464
define <2 x i32> @ashr_lshr_splat_vec(<2 x i32> %x, <2 x i32> %y) {
6565
; CHECK-LABEL: @ashr_lshr_splat_vec(
66-
; CHECK-NEXT: [[CMP1:%.*]] = ashr <2 x i32> [[X:%.*]], [[Y:%.*]]
67-
; CHECK-NEXT: ret <2 x i32> [[CMP1]]
66+
; CHECK-NEXT: [[CMP12:%.*]] = ashr <2 x i32> [[X:%.*]], [[Y:%.*]]
67+
; CHECK-NEXT: ret <2 x i32> [[CMP12]]
6868
;
6969
%cmp = icmp sgt <2 x i32> %x, <i32 -1, i32 -1>
7070
%l = lshr <2 x i32> %x, %y
@@ -75,8 +75,8 @@ define <2 x i32> @ashr_lshr_splat_vec(<2 x i32> %x, <2 x i32> %y) {
7575

7676
define <2 x i32> @ashr_lshr_splat_vec2(<2 x i32> %x, <2 x i32> %y) {
7777
; CHECK-LABEL: @ashr_lshr_splat_vec2(
78-
; CHECK-NEXT: [[CMP1:%.*]] = ashr exact <2 x i32> [[X:%.*]], [[Y:%.*]]
79-
; CHECK-NEXT: ret <2 x i32> [[CMP1]]
78+
; CHECK-NEXT: [[CMP12:%.*]] = ashr exact <2 x i32> [[X:%.*]], [[Y:%.*]]
79+
; CHECK-NEXT: ret <2 x i32> [[CMP12]]
8080
;
8181
%cmp = icmp sgt <2 x i32> %x, <i32 -1, i32 -1>
8282
%l = lshr exact <2 x i32> %x, %y
@@ -87,8 +87,8 @@ define <2 x i32> @ashr_lshr_splat_vec2(<2 x i32> %x, <2 x i32> %y) {
8787

8888
define <2 x i32> @ashr_lshr_splat_vec3(<2 x i32> %x, <2 x i32> %y) {
8989
; CHECK-LABEL: @ashr_lshr_splat_vec3(
90-
; CHECK-NEXT: [[CMP1:%.*]] = ashr <2 x i32> [[X:%.*]], [[Y:%.*]]
91-
; CHECK-NEXT: ret <2 x i32> [[CMP1]]
90+
; CHECK-NEXT: [[CMP12:%.*]] = ashr <2 x i32> [[X:%.*]], [[Y:%.*]]
91+
; CHECK-NEXT: ret <2 x i32> [[CMP12]]
9292
;
9393
%cmp = icmp sgt <2 x i32> %x, <i32 -1, i32 -1>
9494
%l = lshr exact <2 x i32> %x, %y
@@ -99,8 +99,8 @@ define <2 x i32> @ashr_lshr_splat_vec3(<2 x i32> %x, <2 x i32> %y) {
9999

100100
define <2 x i32> @ashr_lshr_splat_vec4(<2 x i32> %x, <2 x i32> %y) {
101101
; CHECK-LABEL: @ashr_lshr_splat_vec4(
102-
; CHECK-NEXT: [[CMP1:%.*]] = ashr <2 x i32> [[X:%.*]], [[Y:%.*]]
103-
; CHECK-NEXT: ret <2 x i32> [[CMP1]]
102+
; CHECK-NEXT: [[CMP12:%.*]] = ashr <2 x i32> [[X:%.*]], [[Y:%.*]]
103+
; CHECK-NEXT: ret <2 x i32> [[CMP12]]
104104
;
105105
%cmp = icmp sgt <2 x i32> %x, <i32 -1, i32 -1>
106106
%l = lshr <2 x i32> %x, %y
@@ -171,8 +171,8 @@ define i32 @ashr_lshr_cst(i32 %x, i32 %y) {
171171

172172
define i32 @ashr_lshr_cst2(i32 %x, i32 %y) {
173173
; CHECK-LABEL: @ashr_lshr_cst2(
174-
; CHECK-NEXT: [[CMP1:%.*]] = ashr i32 [[X:%.*]], 8
175-
; CHECK-NEXT: ret i32 [[CMP1]]
174+
; CHECK-NEXT: [[CMP12:%.*]] = ashr i32 [[X:%.*]], 8
175+
; CHECK-NEXT: ret i32 [[CMP12]]
176176
;
177177
%cmp = icmp sgt i32 %x, -1
178178
%l = lshr i32 %x, 8
@@ -231,8 +231,8 @@ define <2 x i32> @ashr_lshr_inv_nonsplat_vec(<2 x i32> %x, <2 x i32> %y) {
231231

232232
define <2 x i32> @ashr_lshr_vec_undef(<2 x i32> %x, <2 x i32> %y) {
233233
; CHECK-LABEL: @ashr_lshr_vec_undef(
234-
; CHECK-NEXT: [[CMP1:%.*]] = ashr <2 x i32> [[X:%.*]], [[Y:%.*]]
235-
; CHECK-NEXT: ret <2 x i32> [[CMP1]]
234+
; CHECK-NEXT: [[CMP12:%.*]] = ashr <2 x i32> [[X:%.*]], [[Y:%.*]]
235+
; CHECK-NEXT: ret <2 x i32> [[CMP12]]
236236
;
237237
%cmp = icmp sgt <2 x i32> %x, <i32 undef, i32 -1>
238238
%l = lshr <2 x i32> %x, %y
@@ -317,10 +317,10 @@ define i32 @ashr_lshr_shift_wrong_pred(i32 %x, i32 %y, i32 %z) {
317317

318318
define i32 @ashr_lshr_shift_wrong_pred2(i32 %x, i32 %y, i32 %z) {
319319
; CHECK-LABEL: @ashr_lshr_shift_wrong_pred2(
320-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[Z:%.*]], -1
321320
; CHECK-NEXT: [[L:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
322321
; CHECK-NEXT: [[R:%.*]] = ashr i32 [[X]], [[Y]]
323-
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[L]], i32 [[R]]
322+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[Z:%.*]], 0
323+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP1]], i32 [[R]], i32 [[L]]
324324
; CHECK-NEXT: ret i32 [[RET]]
325325
;
326326
%cmp = icmp sge i32 %z, 0
@@ -332,10 +332,10 @@ define i32 @ashr_lshr_shift_wrong_pred2(i32 %x, i32 %y, i32 %z) {
332332

333333
define i32 @ashr_lshr_wrong_operands(i32 %x, i32 %y) {
334334
; CHECK-LABEL: @ashr_lshr_wrong_operands(
335-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], -1
336-
; CHECK-NEXT: [[L:%.*]] = lshr i32 [[X]], [[Y:%.*]]
335+
; CHECK-NEXT: [[L:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
337336
; CHECK-NEXT: [[R:%.*]] = ashr i32 [[X]], [[Y]]
338-
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[R]], i32 [[L]]
337+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X]], 0
338+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP1]], i32 [[L]], i32 [[R]]
339339
; CHECK-NEXT: ret i32 [[RET]]
340340
;
341341
%cmp = icmp sge i32 %x, 0
@@ -347,10 +347,10 @@ define i32 @ashr_lshr_wrong_operands(i32 %x, i32 %y) {
347347

348348
define i32 @ashr_lshr_no_ashr(i32 %x, i32 %y) {
349349
; CHECK-LABEL: @ashr_lshr_no_ashr(
350-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], -1
351-
; CHECK-NEXT: [[L:%.*]] = lshr i32 [[X]], [[Y:%.*]]
350+
; CHECK-NEXT: [[L:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
352351
; CHECK-NEXT: [[R:%.*]] = xor i32 [[X]], [[Y]]
353-
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[L]], i32 [[R]]
352+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X]], 0
353+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP1]], i32 [[R]], i32 [[L]]
354354
; CHECK-NEXT: ret i32 [[RET]]
355355
;
356356
%cmp = icmp sge i32 %x, 0
@@ -362,10 +362,10 @@ define i32 @ashr_lshr_no_ashr(i32 %x, i32 %y) {
362362

363363
define i32 @ashr_lshr_shift_amt_mismatch(i32 %x, i32 %y, i32 %z) {
364364
; CHECK-LABEL: @ashr_lshr_shift_amt_mismatch(
365-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], -1
366-
; CHECK-NEXT: [[L:%.*]] = lshr i32 [[X]], [[Y:%.*]]
365+
; CHECK-NEXT: [[L:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
367366
; CHECK-NEXT: [[R:%.*]] = ashr i32 [[X]], [[Z:%.*]]
368-
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[L]], i32 [[R]]
367+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X]], 0
368+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP1]], i32 [[R]], i32 [[L]]
369369
; CHECK-NEXT: ret i32 [[RET]]
370370
;
371371
%cmp = icmp sge i32 %x, 0
@@ -377,10 +377,10 @@ define i32 @ashr_lshr_shift_amt_mismatch(i32 %x, i32 %y, i32 %z) {
377377

378378
define i32 @ashr_lshr_shift_base_mismatch(i32 %x, i32 %y, i32 %z) {
379379
; CHECK-LABEL: @ashr_lshr_shift_base_mismatch(
380-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], -1
381-
; CHECK-NEXT: [[L:%.*]] = lshr i32 [[X]], [[Y:%.*]]
380+
; CHECK-NEXT: [[L:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
382381
; CHECK-NEXT: [[R:%.*]] = ashr i32 [[Z:%.*]], [[Y]]
383-
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[L]], i32 [[R]]
382+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X]], 0
383+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP1]], i32 [[R]], i32 [[L]]
384384
; CHECK-NEXT: ret i32 [[RET]]
385385
;
386386
%cmp = icmp sge i32 %x, 0
@@ -392,10 +392,10 @@ define i32 @ashr_lshr_shift_base_mismatch(i32 %x, i32 %y, i32 %z) {
392392

393393
define i32 @ashr_lshr_no_lshr(i32 %x, i32 %y) {
394394
; CHECK-LABEL: @ashr_lshr_no_lshr(
395-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], -1
396-
; CHECK-NEXT: [[L:%.*]] = add i32 [[X]], [[Y:%.*]]
395+
; CHECK-NEXT: [[L:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
397396
; CHECK-NEXT: [[R:%.*]] = ashr i32 [[X]], [[Y]]
398-
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[L]], i32 [[R]]
397+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X]], 0
398+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP1]], i32 [[R]], i32 [[L]]
399399
; CHECK-NEXT: ret i32 [[RET]]
400400
;
401401
%cmp = icmp sge i32 %x, 0
@@ -422,10 +422,10 @@ define <2 x i32> @ashr_lshr_vec_wrong_pred(<2 x i32> %x, <2 x i32> %y) {
422422

423423
define <2 x i32> @ashr_lshr_inv_vec_wrong_pred(<2 x i32> %x, <2 x i32> %y) {
424424
; CHECK-LABEL: @ashr_lshr_inv_vec_wrong_pred(
425-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[X:%.*]], <i32 -1, i32 -1>
426-
; CHECK-NEXT: [[L:%.*]] = lshr <2 x i32> [[X]], [[Y:%.*]]
425+
; CHECK-NEXT: [[L:%.*]] = lshr <2 x i32> [[X:%.*]], [[Y:%.*]]
427426
; CHECK-NEXT: [[R:%.*]] = ashr <2 x i32> [[X]], [[Y]]
428-
; CHECK-NEXT: [[RET:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[R]], <2 x i32> [[L]]
427+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <2 x i32> [[X]], zeroinitializer
428+
; CHECK-NEXT: [[RET:%.*]] = select <2 x i1> [[CMP1]], <2 x i32> [[L]], <2 x i32> [[R]]
429429
; CHECK-NEXT: ret <2 x i32> [[RET]]
430430
;
431431
%cmp = icmp sge <2 x i32> %x, zeroinitializer

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,10 +758,10 @@ define <2 x i16> @bitcast_vec_cond_commute3(<4 x i8> %cond, <2 x i16> %pc, <2 x
758758
; CHECK-LABEL: @bitcast_vec_cond_commute3(
759759
; CHECK-NEXT: [[C:%.*]] = mul <2 x i16> [[PC:%.*]], [[PC]]
760760
; CHECK-NEXT: [[D:%.*]] = mul <2 x i16> [[PD:%.*]], [[PD]]
761-
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp sgt <4 x i8> [[COND:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
762761
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i16> [[D]] to <4 x i8>
763762
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i16> [[C]] to <4 x i8>
764-
; CHECK-NEXT: [[TMP3:%.*]] = select <4 x i1> [[DOTNOT]], <4 x i8> [[TMP2]], <4 x i8> [[TMP1]]
763+
; CHECK-NEXT: [[DOTNOT2:%.*]] = icmp slt <4 x i8> [[COND:%.*]], zeroinitializer
764+
; CHECK-NEXT: [[TMP3:%.*]] = select <4 x i1> [[DOTNOT2]], <4 x i8> [[TMP1]], <4 x i8> [[TMP2]]
765765
; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i8> [[TMP3]] to <2 x i16>
766766
; CHECK-NEXT: ret <2 x i16> [[TMP4]]
767767
;

llvm/test/Transforms/InstCombine/truncating-saturate.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ define i16 @testtrunclowhigh(i32 %add, i16 %low, i16 %high) {
123123
; CHECK-NEXT: [[A:%.*]] = add i32 [[ADD:%.*]], 128
124124
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], 256
125125
; CHECK-NEXT: [[T:%.*]] = trunc i32 [[ADD]] to i16
126-
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[ADD]], -1
127-
; CHECK-NEXT: [[F:%.*]] = select i1 [[C]], i16 [[HIGH:%.*]], i16 [[LOW:%.*]]
126+
; CHECK-NEXT: [[C1:%.*]] = icmp slt i32 [[ADD]], 0
127+
; CHECK-NEXT: [[F:%.*]] = select i1 [[C1]], i16 [[LOW:%.*]], i16 [[HIGH:%.*]]
128128
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i16 [[T]], i16 [[F]]
129129
; CHECK-NEXT: ret i16 [[R]]
130130
;

0 commit comments

Comments
 (0)