[PATCH] D74141: [InstCombine] Simplify a umul overflow check to a != 0 && b != 0.
Florian Hahn via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 6 09:55:40 PST 2020
fhahn created this revision.
fhahn added reviewers: nikic, RKSimon, lebedev.ri, spatel.
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.
This patch adds a simplification if an OR weakens the overflow condition
for umul.with.overflow by treating any non-zero result as overflow. In that
case, we overflow if both umul.with.overflow operands are != 0, as in that
case the result can only be 0, iff the multiplication overflows.
Code like this is generated by code using __builtin_mul_overflow with
negative integer constants, e.g.
bool test(unsigned long long v, unsigned long long *res) {
return __builtin_mul_overflow(v, -4775807LL, res);
}
This simplification is very specific and I am not sure if visitOr is the
best place for it. Any other suggestions?
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D74141
Files:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/umul-signed.ll
Index: llvm/test/Transforms/InstCombine/umul-signed.ll
===================================================================
--- llvm/test/Transforms/InstCombine/umul-signed.ll
+++ llvm/test/Transforms/InstCombine/umul-signed.ll
@@ -14,13 +14,10 @@
define i1 @test1(i64 %a, i64* %ptr) {
; CHECK-LABEL: @test1(
-; CHECK-NEXT: [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 -4775807)
-; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1
-; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i64, i1 } [[RES]], 0
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[MUL]], 0
-; CHECK-NEXT: [[OVERFLOW_1:%.*]] = or i1 [[OVERFLOW]], [[CMP]]
+; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[A:%.*]], -4775807
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[A]], 0
; CHECK-NEXT: store i64 [[MUL]], i64* [[PTR:%.*]], align 8
-; CHECK-NEXT: ret i1 [[OVERFLOW_1]]
+; CHECK-NEXT: ret i1 [[TMP1]]
;
%res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 -4775807)
%overflow = extractvalue { i64, i1 } %res, 1
@@ -33,13 +30,10 @@
define i1 @test1_or_ops_swapped(i64 %a, i64* %ptr) {
; CHECK-LABEL: @test1_or_ops_swapped(
-; CHECK-NEXT: [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 -4775807)
-; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1
-; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i64, i1 } [[RES]], 0
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[MUL]], 0
-; CHECK-NEXT: [[OVERFLOW_1:%.*]] = or i1 [[CMP]], [[OVERFLOW]]
+; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[A:%.*]], -4775807
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[A]], 0
; CHECK-NEXT: store i64 [[MUL]], i64* [[PTR:%.*]], align 8
-; CHECK-NEXT: ret i1 [[OVERFLOW_1]]
+; CHECK-NEXT: ret i1 [[TMP1]]
;
%res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 -4775807)
%overflow = extractvalue { i64, i1 } %res, 1
@@ -53,14 +47,10 @@
define i1 @test2(i64 %a, i64* %ptr) {
; CHECK-LABEL: @test2(
-; CHECK-NEXT: [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 10000)
-; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1
-; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i64, i1 } [[RES]], 0
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[MUL]], 0
-; CHECK-NEXT: [[OVERFLOW_1:%.*]] = or i1 [[OVERFLOW]], [[CMP]]
-; CHECK-NEXT: [[NEG:%.*]] = sub i64 0, [[MUL]]
-; CHECK-NEXT: store i64 [[NEG]], i64* [[PTR:%.*]], align 8
-; CHECK-NEXT: ret i1 [[OVERFLOW_1]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[A:%.*]], 0
+; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i64 [[A]], -10000
+; CHECK-NEXT: store i64 [[MUL_NEG]], i64* [[PTR:%.*]], align 8
+; CHECK-NEXT: ret i1 [[TMP1]]
;
%res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 10000)
%overflow = extractvalue { i64, i1 } %res, 1
Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2723,6 +2723,25 @@
canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(I))
return V;
+ CmpInst::Predicate Pred;
+ Value *UMul1, *UMul2;
+ // Check if the OR weakens the overflow condition for umul.with.overflow by
+ // treating any non-zero result as overflow. In that case, we overflow if both
+ // umul.with.overflow operands are != 0, as in that case the result can only
+ // be 0, iff the multiplication overflows.
+ auto P = m_ICmp(Pred, m_ExtractValue<0>(m_Value(UMul2)), m_SpecificInt(0));
+ if (match(&I, m_Or(m_OneUse(m_ExtractValue<1>(m_Value(UMul1))), P)) ||
+ match(&I, m_Or(P, m_OneUse(m_ExtractValue<1>(m_Value(UMul1)))))) {
+ Value *A, *B;
+ if (Pred == CmpInst::ICMP_NE && UMul1 == UMul2 &&
+ match(UMul1, m_Intrinsic<Intrinsic::umul_with_overflow>(m_Value(A),
+ m_Value(B))))
+
+ return BinaryOperator::CreateAnd(
+ Builder.CreateICmpNE(A, ConstantInt::get(A->getType(), 0)),
+ Builder.CreateICmpNE(A, ConstantInt::get(B->getType(), 0)));
+ }
+
return nullptr;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D74141.242932.patch
Type: text/x-patch
Size: 4289 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200206/63cbc953/attachment.bin>
More information about the llvm-commits
mailing list