Skip to content

Commit e635520

Browse files
authored
[DAG] computeKnownBits - abs(x) will be zero in the upper bits if x is sign-extended (#94382)
As reported on #94344 - if x has more than one signbit, then the upper bits of its absolute value are guaranteed to be zero Alive2: https://alive2.llvm.org/ce/z/a87fHU Fixes #94344
1 parent 043cc5a commit e635520

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4051,6 +4051,8 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
40514051
case ISD::ABS: {
40524052
Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
40534053
Known = Known2.abs();
4054+
Known.Zero.setHighBits(
4055+
ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1) - 1);
40544056
break;
40554057
}
40564058
case ISD::USUBSAT: {

llvm/test/CodeGen/X86/combine-abs.ll

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,50 @@ define <8 x i32> @combine_v8i32_abs_pos(<8 x i32> %a) {
201201
ret <8 x i32> %2
202202
}
203203

204+
; (abs x) upper bits are known zero if x has extra sign bits
205+
define i32 @combine_i32_abs_zerosign(i32 %a) {
206+
; CHECK-LABEL: combine_i32_abs_zerosign:
207+
; CHECK: # %bb.0:
208+
; CHECK-NEXT: xorl %eax, %eax
209+
; CHECK-NEXT: retq
210+
%1 = ashr i32 %a, 15
211+
%2 = call i32 @llvm.abs.i32(i32 %1, i1 false)
212+
%3 = and i32 %2, -524288 ; 0xFFF80000
213+
ret i32 %3
214+
}
215+
216+
define <8 x i16> @combine_v8i16_abs_zerosign(<8 x i16> %a) {
217+
; SSE-LABEL: combine_v8i16_abs_zerosign:
218+
; SSE: # %bb.0:
219+
; SSE-NEXT: xorps %xmm0, %xmm0
220+
; SSE-NEXT: retq
221+
;
222+
; AVX-LABEL: combine_v8i16_abs_zerosign:
223+
; AVX: # %bb.0:
224+
; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0
225+
; AVX-NEXT: retq
226+
%1 = ashr <8 x i16> %a, <i16 7, i16 8, i16 9, i16 10, i16 11, i16 12, i16 13, i16 14>
227+
%2 = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %1, i1 false)
228+
%3 = and <8 x i16> %2, <i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768>
229+
ret <8 x i16> %3
230+
}
231+
232+
; negative test - mask extends beyond known zero bits
233+
define i32 @combine_i32_abs_zerosign_negative(i32 %a) {
234+
; CHECK-LABEL: combine_i32_abs_zerosign_negative:
235+
; CHECK: # %bb.0:
236+
; CHECK-NEXT: sarl $3, %edi
237+
; CHECK-NEXT: movl %edi, %eax
238+
; CHECK-NEXT: negl %eax
239+
; CHECK-NEXT: cmovsl %edi, %eax
240+
; CHECK-NEXT: andl $536346624, %eax # imm = 0x1FF80000
241+
; CHECK-NEXT: retq
242+
%1 = ashr i32 %a, 3
243+
%2 = call i32 @llvm.abs.i32(i32 %1, i1 false)
244+
%3 = and i32 %2, -524288 ; 0xFFF80000
245+
ret i32 %3
246+
}
247+
204248
declare <16 x i8> @llvm.abs.v16i8(<16 x i8>, i1) nounwind readnone
205249
declare <4 x i32> @llvm.abs.v4i32(<4 x i32>, i1) nounwind readnone
206250
declare <8 x i16> @llvm.abs.v8i16(<8 x i16>, i1) nounwind readnone

0 commit comments

Comments
 (0)