forked from OSchip/llvm-project
[InstCombine] add (sext i1 X), 1 --> zext (not X)
http://rise4fun.com/Alive/i8Q A narrow bitwise logic op is obviously better than math for value tracking, and zext is better than sext. Typically, the 'not' will be folded into an icmp predicate. The IR difference would even survive through codegen for x86, so we would see worse code: https://godbolt.org/g/C14HMF one_or_zero(int, int): # @one_or_zero(int, int) xorl %eax, %eax cmpl %esi, %edi setle %al retq one_or_zero_alt(int, int): # @one_or_zero_alt(int, int) xorl %ecx, %ecx cmpl %esi, %edi setg %cl movl $1, %eax subl %ecx, %eax retq llvm-svn: 306243
This commit is contained in:
parent
72f991cded
commit
2f3ead7adc
|
@ -988,15 +988,24 @@ static Instruction *foldAddWithConstant(BinaryOperator &Add,
|
|||
return new ZExtInst(Builder.CreateNUWAdd(X, NewC), Ty);
|
||||
}
|
||||
|
||||
// Shifts and add used to flip and mask off the low bit:
|
||||
// add (ashr (shl i32 X, 31), 31), 1 --> and (not X), 1
|
||||
const APInt *C3;
|
||||
if (C->isOneValue() &&
|
||||
match(Op0,
|
||||
m_OneUse(m_AShr(m_Shl(m_Value(X), m_APInt(C2)), m_APInt(C3)))) &&
|
||||
C2 == C3 && *C2 == Ty->getScalarSizeInBits() - 1) {
|
||||
Value *NotX = Builder.CreateNot(X);
|
||||
return BinaryOperator::CreateAnd(NotX, ConstantInt::get(Ty, 1));
|
||||
if (C->isOneValue() && Op0->hasOneUse()) {
|
||||
// add (sext i1 X), 1 --> zext (not X)
|
||||
// TODO: The smallest IR representation is (select X, 0, 1), and that would
|
||||
// not require the one-use check. But we need to remove a transform in
|
||||
// visitSelect and make sure that IR value tracking for select is equal or
|
||||
// better than for these ops.
|
||||
if (match(Op0, m_SExt(m_Value(X))) &&
|
||||
X->getType()->getScalarSizeInBits() == 1)
|
||||
return new ZExtInst(Builder.CreateNot(X), Ty);
|
||||
|
||||
// Shifts and add used to flip and mask off the low bit:
|
||||
// add (ashr (shl i32 X, 31), 31), 1 --> and (not X), 1
|
||||
const APInt *C3;
|
||||
if (match(Op0, m_AShr(m_Shl(m_Value(X), m_APInt(C2)), m_APInt(C3))) &&
|
||||
C2 == C3 && *C2 == Ty->getScalarSizeInBits() - 1) {
|
||||
Value *NotX = Builder.CreateNot(X);
|
||||
return BinaryOperator::CreateAnd(NotX, ConstantInt::get(Ty, 1));
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||
|
||||
; TODO: This should be canonicalized to either a select or xor+zext.
|
||||
|
||||
define i32 @select_0_or_1_from_bool(i1 %x) {
|
||||
; CHECK-LABEL: @select_0_or_1_from_bool(
|
||||
; CHECK-NEXT: [[EXT:%.*]] = sext i1 %x to i32
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[EXT]], 1
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = xor i1 %x, true
|
||||
; CHECK-NEXT: [[ADD:%.*]] = zext i1 [[TMP1]] to i32
|
||||
; CHECK-NEXT: ret i32 [[ADD]]
|
||||
;
|
||||
%ext = sext i1 %x to i32
|
||||
|
@ -14,12 +12,10 @@ define i32 @select_0_or_1_from_bool(i1 %x) {
|
|||
ret i32 %add
|
||||
}
|
||||
|
||||
; TODO: This should be canonicalized to either a select or xor+zext.
|
||||
|
||||
define <2 x i32> @select_0_or_1_from_bool_vec(<2 x i1> %x) {
|
||||
; CHECK-LABEL: @select_0_or_1_from_bool_vec(
|
||||
; CHECK-NEXT: [[EXT:%.*]] = sext <2 x i1> %x to <2 x i32>
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add nsw <2 x i32> [[EXT]], <i32 1, i32 1>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i1> %x, <i1 true, i1 true>
|
||||
; CHECK-NEXT: [[ADD:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i32>
|
||||
; CHECK-NEXT: ret <2 x i32> [[ADD]]
|
||||
;
|
||||
%ext = sext <2 x i1> %x to <2 x i32>
|
||||
|
|
Loading…
Reference in New Issue