From e392e54cc90689ff8f2ea0498c4e5e5815c0f762 Mon Sep 17 00:00:00 2001 From: David Bolvansky Date: Thu, 20 Jun 2019 17:04:14 +0000 Subject: [PATCH] [InstCombine] cttz(-x) -> cttz(x) Summary: Signedness does not change number of trailing zeros. Reviewers: spatel, lebedev.ri, nikic Reviewed By: spatel Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63534 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363951 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineCalls.cpp | 6 +++ test/Transforms/InstCombine/cttz-negative.ll | 42 ++++++++++++------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index e366c379e9b..4bd1246cbf7 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1194,6 +1194,12 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombiner &IC) { return CallInst::Create(F, {X, II.getArgOperand(1)}); } + // cttz(-x) -> cttz(x) + if (IsTZ && match(Op0, m_Neg(m_Value(X)))) { + II.setOperand(0, X); + return &II; + } + KnownBits Known = IC.computeKnownBits(Op0, 0, &II); // Create a mask for bits above (ctlz) or below (cttz) the first known one. diff --git a/test/Transforms/InstCombine/cttz-negative.ll b/test/Transforms/InstCombine/cttz-negative.ll index 44bdae62c30..feb7495fe3c 100644 --- a/test/Transforms/InstCombine/cttz-negative.ll +++ b/test/Transforms/InstCombine/cttz-negative.ll @@ -3,44 +3,53 @@ define i32 @cttz_neg_value(i32 %x) { ; CHECK-LABEL: @cttz_neg_value( -; CHECK-NEXT: [[A:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.cttz.i32(i32 [[A]], i1 false), !range !0 +; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false), !range !0 +; CHECK-NEXT: ret i32 [[B]] +; + %a = sub i32 0, %x + %b = tail call i32 @llvm.cttz.i32(i32 %a) + ret i32 %b +} + +define i32 @cttz_neg_value_multiuse(i32 %x) { +; CHECK-LABEL: @cttz_neg_value_multiuse( +; CHECK-NEXT: [[A:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: call void @use(i32 [[A]]) +; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.cttz.i32(i32 [[X]], i1 false), !range !0 ; CHECK-NEXT: ret i32 [[B]] ; - %a = sub nsw i32 0, %x + %a = sub i32 0, %x + call void @use(i32 %a) %b = tail call i32 @llvm.cttz.i32(i32 %a) ret i32 %b } define i64 @cttz_neg_value_64(i64 %x) { ; CHECK-LABEL: @cttz_neg_value_64( -; CHECK-NEXT: [[A:%.*]] = sub nsw i64 0, [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[A]], i1 true), !range !1 +; CHECK-NEXT: [[B:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 true), !range !1 ; CHECK-NEXT: ret i64 [[B]] ; - %a = sub nsw i64 0, %x + %a = sub i64 0, %x %b = tail call i64 @llvm.cttz.i64(i64 %a, i1 true) ret i64 %b } define i64 @cttz_neg_value2_64(i64 %x) { ; CHECK-LABEL: @cttz_neg_value2_64( -; CHECK-NEXT: [[A:%.*]] = sub nsw i64 0, [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[A]], i1 false), !range !1 +; CHECK-NEXT: [[B:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false), !range !1 ; CHECK-NEXT: ret i64 [[B]] ; - %a = sub nsw i64 0, %x + %a = sub i64 0, %x %b = tail call i64 @llvm.cttz.i64(i64 %a, i1 false) ret i64 %b } define <2 x i64> @cttz_neg_value_vec(<2 x i64> %x) { ; CHECK-LABEL: @cttz_neg_value_vec( -; CHECK-NEXT: [[A:%.*]] = sub nsw <2 x i64> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[A]], i1 false) +; CHECK-NEXT: [[B:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[X:%.*]], i1 false) ; CHECK-NEXT: ret <2 x i64> [[B]] ; - %a = sub nsw <2 x i64> zeroinitializer, %x + %a = sub <2 x i64> zeroinitializer, %x %b = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %a) ret <2 x i64> %b } @@ -49,26 +58,27 @@ define <2 x i64> @cttz_neg_value_vec(<2 x i64> %x) { define i32 @cttz_nonneg_value(i32 %x) { ; CHECK-LABEL: @cttz_nonneg_value( -; CHECK-NEXT: [[A:%.*]] = sub nsw i32 1, [[X:%.*]] +; CHECK-NEXT: [[A:%.*]] = sub i32 1, [[X:%.*]] ; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.cttz.i32(i32 [[A]], i1 false), !range !0 ; CHECK-NEXT: ret i32 [[B]] ; - %a = sub nsw i32 1, %x + %a = sub i32 1, %x %b = tail call i32 @llvm.cttz.i32(i32 %a) ret i32 %b } define <2 x i64> @cttz_nonneg_value_vec(<2 x i64> %x) { ; CHECK-LABEL: @cttz_nonneg_value_vec( -; CHECK-NEXT: [[A:%.*]] = sub nsw <2 x i64> , [[X:%.*]] +; CHECK-NEXT: [[A:%.*]] = sub <2 x i64> , [[X:%.*]] ; CHECK-NEXT: [[B:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[A]], i1 false) ; CHECK-NEXT: ret <2 x i64> [[B]] ; - %a = sub nsw <2 x i64> , %x + %a = sub <2 x i64> , %x %b = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %a) ret <2 x i64> %b } +declare void @use(i32 %a) declare i32 @llvm.cttz.i32(i32) declare i64 @llvm.cttz.i64(i64, i1) declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>) -- 2.40.0