Skip to content

Commit e61e260

Browse files
authored
[InstCombine] Fold mul (sext bool X), Y into select X, -Y, 0 (#84792)
Alive2: https://alive2.llvm.org/ce/z/n_ns-W Resolve #84608
1 parent ff2fb2a commit e61e260

File tree

3 files changed

+102
-5
lines changed

3 files changed

+102
-5
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,14 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
448448
if (match(Op1, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))
449449
return SelectInst::Create(X, Op0, ConstantInt::getNullValue(Ty));
450450

451+
// mul (sext X), Y -> select X, -Y, 0
452+
// mul Y, (sext X) -> select X, -Y, 0
453+
if (match(&I, m_c_Mul(m_OneUse(m_SExt(m_Value(X))), m_Value(Y))) &&
454+
X->getType()->isIntOrIntVectorTy(1))
455+
return SelectInst::Create(
456+
X, Builder.CreateNeg(Y, "", /*HasNUW=*/false, I.hasNoSignedWrap()),
457+
ConstantInt::getNullValue(Op0->getType()));
458+
451459
Constant *ImmC;
452460
if (match(Op1, m_ImmConstant(ImmC))) {
453461
// (sext bool X) * C --> X ? -C : 0

llvm/test/Transforms/InstCombine/mul.ll

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,3 +2049,94 @@ define i32 @zext_negpow2_use(i8 %x) {
20492049
%r = mul i32 %zx, -16777216 ; -1 << 24
20502050
ret i32 %r
20512051
}
2052+
2053+
define i32 @mul_sext_icmp_with_zero(i32 %x) {
2054+
; CHECK-LABEL: @mul_sext_icmp_with_zero(
2055+
; CHECK-NEXT: ret i32 0
2056+
;
2057+
%cmp = icmp eq i32 %x, 0
2058+
%sext = sext i1 %cmp to i32
2059+
%mul = mul i32 %sext, %x
2060+
ret i32 %mul
2061+
}
2062+
2063+
define i32 @test_mul_sext_bool(i1 %x, i32 %y) {
2064+
; CHECK-LABEL: @test_mul_sext_bool(
2065+
; CHECK-NEXT: [[Y_NEG:%.*]] = sub i32 0, [[Y:%.*]]
2066+
; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[Y_NEG]], i32 0
2067+
; CHECK-NEXT: ret i32 [[MUL]]
2068+
;
2069+
%sext = sext i1 %x to i32
2070+
%mul = mul i32 %sext, %y
2071+
ret i32 %mul
2072+
}
2073+
2074+
define i32 @test_mul_sext_bool_nuw(i1 %x, i32 %y) {
2075+
; CHECK-LABEL: @test_mul_sext_bool_nuw(
2076+
; CHECK-NEXT: [[Y_NEG:%.*]] = sub i32 0, [[Y:%.*]]
2077+
; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[Y_NEG]], i32 0
2078+
; CHECK-NEXT: ret i32 [[MUL]]
2079+
;
2080+
%sext = sext i1 %x to i32
2081+
%mul = mul nuw i32 %sext, %y
2082+
ret i32 %mul
2083+
}
2084+
2085+
define i32 @test_mul_sext_bool_nsw(i1 %x, i32 %y) {
2086+
; CHECK-LABEL: @test_mul_sext_bool_nsw(
2087+
; CHECK-NEXT: [[Y_NEG:%.*]] = sub nsw i32 0, [[Y:%.*]]
2088+
; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[Y_NEG]], i32 0
2089+
; CHECK-NEXT: ret i32 [[MUL]]
2090+
;
2091+
%sext = sext i1 %x to i32
2092+
%mul = mul nsw i32 %sext, %y
2093+
ret i32 %mul
2094+
}
2095+
2096+
define i32 @test_mul_sext_bool_nuw_nsw(i1 %x, i32 %y) {
2097+
; CHECK-LABEL: @test_mul_sext_bool_nuw_nsw(
2098+
; CHECK-NEXT: [[Y_NEG:%.*]] = sub nsw i32 0, [[Y:%.*]]
2099+
; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[Y_NEG]], i32 0
2100+
; CHECK-NEXT: ret i32 [[MUL]]
2101+
;
2102+
%sext = sext i1 %x to i32
2103+
%mul = mul nuw nsw i32 %sext, %y
2104+
ret i32 %mul
2105+
}
2106+
2107+
define i32 @test_mul_sext_bool_commuted(i1 %x, i32 %y) {
2108+
; CHECK-LABEL: @test_mul_sext_bool_commuted(
2109+
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[Y:%.*]], -2
2110+
; CHECK-NEXT: [[YY_NEG1:%.*]] = add i32 [[TMP1]], 1
2111+
; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[YY_NEG1]], i32 0
2112+
; CHECK-NEXT: ret i32 [[MUL]]
2113+
;
2114+
%yy = xor i32 %y, 1
2115+
%sext = sext i1 %x to i32
2116+
%mul = mul i32 %yy, %sext
2117+
ret i32 %mul
2118+
}
2119+
2120+
define i32 @test_mul_sext_nonbool(i2 %x, i32 %y) {
2121+
; CHECK-LABEL: @test_mul_sext_nonbool(
2122+
; CHECK-NEXT: [[SEXT:%.*]] = sext i2 [[X:%.*]] to i32
2123+
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SEXT]], [[Y:%.*]]
2124+
; CHECK-NEXT: ret i32 [[MUL]]
2125+
;
2126+
%sext = sext i2 %x to i32
2127+
%mul = mul i32 %sext, %y
2128+
ret i32 %mul
2129+
}
2130+
2131+
define i32 @test_mul_sext_multiuse(i1 %x, i32 %y) {
2132+
; CHECK-LABEL: @test_mul_sext_multiuse(
2133+
; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[X:%.*]] to i32
2134+
; CHECK-NEXT: tail call void @use(i32 [[SEXT]])
2135+
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SEXT]], [[Y:%.*]]
2136+
; CHECK-NEXT: ret i32 [[MUL]]
2137+
;
2138+
%sext = sext i1 %x to i32
2139+
tail call void @use(i32 %sext)
2140+
%mul = mul i32 %sext, %y
2141+
ret i32 %mul
2142+
}

llvm/test/Transforms/InstCombine/sub-xor-cmp.ll

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,9 @@ define i64 @sext_diff_i1_xor_sub_1(i64 %a, i1 %b, i1 %c) {
117117
define i64 @sext_multi_uses(i64 %a, i1 %b, i64 %x) {
118118
; CHECK-LABEL: define i64 @sext_multi_uses(
119119
; CHECK-SAME: i64 [[A:%.*]], i1 [[B:%.*]], i64 [[X:%.*]]) {
120-
; CHECK-NEXT: [[C:%.*]] = sext i1 [[B]] to i64
121-
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[A]]
122-
; CHECK-NEXT: [[E:%.*]] = select i1 [[B]], i64 [[TMP1]], i64 [[A]]
123-
; CHECK-NEXT: [[F:%.*]] = mul i64 [[C]], [[X]]
124-
; CHECK-NEXT: [[R:%.*]] = add i64 [[F]], [[E]]
120+
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[X]], [[A]]
121+
; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]]
122+
; CHECK-NEXT: [[R:%.*]] = select i1 [[B]], i64 [[TMP2]], i64 [[A]]
125123
; CHECK-NEXT: ret i64 [[R]]
126124
;
127125
%c = sext i1 %b to i64

0 commit comments

Comments
 (0)