Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1194,6 +1194,17 @@ return CallInst::Create(F, {X, II.getArgOperand(1)}); } + // cttz(abs(x)) -> cttz(x) + Value *Y; + const auto *SI = dyn_cast(Op0); + if (IsTZ && Op0->hasOneUse() && SI) { + SelectPatternFlavor SPF = matchSelectPattern(Op0, X, Y).Flavor; + if (SPF == SPF_ABS) { + II.setOperand(0, X); + return ⅈ + } + } + KnownBits Known = IC.computeKnownBits(Op0, 0, &II); // Create a mask for bits above (ctlz) or below (cttz) the first known one. Index: test/Transforms/InstCombine/cttz-abs.ll =================================================================== --- test/Transforms/InstCombine/cttz-abs.ll +++ test/Transforms/InstCombine/cttz-abs.ll @@ -3,10 +3,7 @@ define i32 @cttz_abs(i32 %x) { ; CHECK-LABEL: @cttz_abs( -; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X:%.*]], 0 -; CHECK-NEXT: [[S:%.*]] = sub nsw i32 0, [[X]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[S]], i32 [[X]] -; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[D]], i1 true), !range !0 +; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true), !range !0 ; CHECK-NEXT: ret i32 [[R]] ; %c = icmp slt i32 %x, 0 @@ -20,9 +17,7 @@ ; CHECK-LABEL: @cttz_abs2( ; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @use_cond(i1 [[C]]) -; CHECK-NEXT: [[S:%.*]] = sub nsw i32 0, [[X]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[S]] -; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[D]], i1 true), !range !0 +; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true), !range !0 ; CHECK-NEXT: ret i32 [[R]] ; %c = icmp sgt i32 %x, 0 @@ -37,9 +32,7 @@ ; CHECK-LABEL: @cttz_abs3( ; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[X:%.*]], -1 ; CHECK-NEXT: call void @use_cond(i1 [[C]]) -; CHECK-NEXT: [[S:%.*]] = sub nsw i32 0, [[X]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[S]] -; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[D]], i1 true), !range !0 +; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true), !range !0 ; CHECK-NEXT: ret i32 [[R]] ; %c = icmp sgt i32 %x, -1 @@ -52,10 +45,7 @@ define i32 @cttz_abs4(i32 %x) { ; CHECK-LABEL: @cttz_abs4( -; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X:%.*]], 0 -; CHECK-NEXT: [[S:%.*]] = sub nsw i32 0, [[X]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[S]], i32 [[X]] -; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[D]], i1 true), !range !0 +; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true), !range !0 ; CHECK-NEXT: ret i32 [[R]] ; %c = icmp slt i32 %x, 1 @@ -67,10 +57,7 @@ define i64 @cttz_abs_64(i64 %x) { ; CHECK-LABEL: @cttz_abs_64( -; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[X:%.*]], 0 -; CHECK-NEXT: [[S:%.*]] = sub nsw i64 0, [[X]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i64 [[S]], i64 [[X]] -; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.cttz.i64(i64 [[D]], i1 false), !range !1 +; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false), !range !1 ; CHECK-NEXT: ret i64 [[R]] ; %c = icmp slt i64 %x, 0