Skip to content

Commit 43c6fb2

Browse files
authored
[InstCombine] Update the select operand when the cond is trunc and has the nuw or nsw property. (llvm#105914)
This patch updates the select operand when the cond has the nuw or nsw property. Considering the semantics of the nuw and nsw flag, if there is no poison value in this expression, this code assumes that X can only be 0, 1 or -1. close: llvm#96765 alive2: https://alive2.llvm.org/ce/z/3n3n2Q
1 parent 99b85ca commit 43c6fb2

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4201,5 +4201,24 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
42014201
}
42024202
}
42034203

4204+
// select (trunc nuw X to i1), X, Y --> select (trunc nuw X to i1), 1, Y
4205+
// select (trunc nuw X to i1), Y, X --> select (trunc nuw X to i1), Y, 0
4206+
// select (trunc nsw X to i1), X, Y --> select (trunc nsw X to i1), -1, Y
4207+
// select (trunc nsw X to i1), Y, X --> select (trunc nsw X to i1), Y, 0
4208+
Value *Trunc;
4209+
if (match(CondVal, m_NUWTrunc(m_Value(Trunc)))) {
4210+
if (TrueVal == Trunc)
4211+
return replaceOperand(SI, 1, ConstantInt::get(TrueVal->getType(), 1));
4212+
if (FalseVal == Trunc)
4213+
return replaceOperand(SI, 2, ConstantInt::get(FalseVal->getType(), 0));
4214+
}
4215+
if (match(CondVal, m_NSWTrunc(m_Value(Trunc)))) {
4216+
if (TrueVal == Trunc)
4217+
return replaceOperand(SI, 1,
4218+
Constant::getAllOnesValue(TrueVal->getType()));
4219+
if (FalseVal == Trunc)
4220+
return replaceOperand(SI, 2, ConstantInt::get(FalseVal->getType(), 0));
4221+
}
4222+
42044223
return nullptr;
42054224
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3+
4+
define i8 @fold_select_trunc_nuw_true(i8 %x, i8 %y) {
5+
; CHECK-LABEL: @fold_select_trunc_nuw_true(
6+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1
7+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 1, i8 [[Y:%.*]]
8+
; CHECK-NEXT: ret i8 [[RET]]
9+
;
10+
%trunc = trunc nuw i8 %x to i1
11+
%ret = select i1 %trunc, i8 %x, i8 %y
12+
ret i8 %ret
13+
}
14+
15+
define i8 @fold_select_trunc_nuw_false(i8 %x, i8 %y) {
16+
; CHECK-LABEL: @fold_select_trunc_nuw_false(
17+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1
18+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 [[Y:%.*]], i8 0
19+
; CHECK-NEXT: ret i8 [[RET]]
20+
;
21+
%trunc = trunc nuw i8 %x to i1
22+
%ret = select i1 %trunc, i8 %y, i8 %x
23+
ret i8 %ret
24+
}
25+
26+
define i128 @fold_select_trunc_nsw_true(i128 %x, i128 %y) {
27+
; CHECK-LABEL: @fold_select_trunc_nsw_true(
28+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nsw i128 [[X:%.*]] to i1
29+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i128 -1, i128 [[Y:%.*]]
30+
; CHECK-NEXT: ret i128 [[RET]]
31+
;
32+
%trunc = trunc nsw i128 %x to i1
33+
%ret = select i1 %trunc, i128 %x, i128 %y
34+
ret i128 %ret
35+
}
36+
37+
define i8 @fold_select_trunc_nsw_false(i8 %x, i8 %y) {
38+
; CHECK-LABEL: @fold_select_trunc_nsw_false(
39+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nsw i8 [[X:%.*]] to i1
40+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 [[Y:%.*]], i8 0
41+
; CHECK-NEXT: ret i8 [[RET]]
42+
;
43+
%trunc = trunc nsw i8 %x to i1
44+
%ret = select i1 %trunc, i8 %y, i8 %x
45+
ret i8 %ret
46+
}
47+
48+
define i8 @fold_select_trunc_negative(i8 %x, i8 %y) {
49+
; CHECK-LABEL: @fold_select_trunc_negative(
50+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1
51+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[TRUNC]], i8 [[X]], i8 [[Y:%.*]]
52+
; CHECK-NEXT: ret i8 [[RET]]
53+
;
54+
%trunc = trunc i8 %x to i1
55+
%ret = select i1 %trunc, i8 %x, i8 %y
56+
ret i8 %ret
57+
}
58+
59+
define <2 x i8> @fold_select_trunc_vector(<2 x i8> %x, <2 x i8> %y) {
60+
; CHECK-LABEL: @fold_select_trunc_vector(
61+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw <2 x i8> [[X:%.*]] to <2 x i1>
62+
; CHECK-NEXT: [[RET:%.*]] = select <2 x i1> [[TRUNC]], <2 x i8> <i8 1, i8 1>, <2 x i8> [[Y:%.*]]
63+
; CHECK-NEXT: ret <2 x i8> [[RET]]
64+
;
65+
%trunc = trunc nuw <2 x i8> %x to <2 x i1>
66+
%ret = select <2 x i1> %trunc, <2 x i8> %x, <2 x i8> %y
67+
ret <2 x i8> %ret
68+
}

0 commit comments

Comments
 (0)