Skip to content

Commit

Permalink
[InstCombine] allow more narrowing transforms for logic ops
Browse files Browse the repository at this point in the history
We had a limited version of this for scalar 'and'; this expands
the transform to 'or' and 'xor' and allows vectors types too.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288273 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
rotateright committed Nov 30, 2016
1 parent ba32f78 commit b34fe0f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 21 deletions.
32 changes: 23 additions & 9 deletions lib/Transforms/InstCombine/InstCombineCasts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,26 @@ static Instruction *foldVecTruncToExtElt(TruncInst &Trunc, InstCombiner &IC,
return ExtractElementInst::Create(VecInput, IC.Builder->getInt32(Elt));
}

/// Try to narrow the width of bitwise logic instructions with constants.
Instruction *InstCombiner::shrinkBitwiseLogic(TruncInst &Trunc) {
Type *SrcTy = Trunc.getSrcTy();
Type *DestTy = Trunc.getType();
if (isa<IntegerType>(SrcTy) && !ShouldChangeType(SrcTy, DestTy))
return nullptr;

BinaryOperator *LogicOp;
Constant *C;
if (!match(Trunc.getOperand(0), m_OneUse(m_BinOp(LogicOp))) ||
!LogicOp->isBitwiseLogicOp() ||
!match(LogicOp->getOperand(1), m_Constant(C)))
return nullptr;

// trunc (logic X, C) --> logic (trunc X, C')
Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy);
Value *NarrowOp0 = Builder->CreateTrunc(LogicOp->getOperand(0), DestTy);
return BinaryOperator::Create(LogicOp->getOpcode(), NarrowOp0, NarrowC);
}

Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
if (Instruction *Result = commonCastTransforms(CI))
return Result;
Expand Down Expand Up @@ -531,17 +551,11 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
}
}

if (Instruction *I = shrinkBitwiseLogic(CI))
return I;

if (Src->hasOneUse() && isa<IntegerType>(SrcTy) &&
ShouldChangeType(SrcTy, DestTy)) {

// Transform "trunc (and X, cst)" -> "and (trunc X), cst" so long as the
// dest type is native.
if (match(Src, m_And(m_Value(A), m_ConstantInt(Cst)))) {
Value *NewTrunc = Builder->CreateTrunc(A, DestTy, A->getName() + ".tr");
return BinaryOperator::CreateAnd(NewTrunc,
ConstantExpr::getTrunc(Cst, DestTy));
}

// Transform "trunc (shl X, cst)" -> "shl (trunc X), cst" so long as the
// dest type is native and cst < dest size.
if (match(Src, m_Shl(m_Value(A), m_ConstantInt(Cst))) &&
Expand Down
1 change: 1 addition & 0 deletions lib/Transforms/InstCombine/InstCombineInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner
Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
Instruction *foldCastedBitwiseLogic(BinaryOperator &I);
Instruction *shrinkBitwiseLogic(TruncInst &Trunc);
Instruction *optimizeBitCastFromPhi(CastInst &CI, PHINode *PN);

/// Determine if a pair of casts can be replaced by a single cast.
Expand Down
24 changes: 12 additions & 12 deletions test/Transforms/InstCombine/narrow.ll
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ define i1 @test1(i32 %A, i32 %B) {
ret i1 %ELIM3
}

; TODO: The next 6 (3 logic ops * (scalar+vector)) tests show potential cases for narrowing a bitwise logic op.
; The next 6 (3 logic ops * (scalar+vector)) tests show potential cases for narrowing a bitwise logic op.

define i32 @shrink_xor(i64 %a) {
; CHECK-LABEL: @shrink_xor(
; CHECK-NEXT: [[XOR:%.*]] = xor i64 %a, 1
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[XOR]] to i32
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 %a to i32
; CHECK-NEXT: [[TRUNC:%.*]] = xor i32 [[TMP1]], 1
; CHECK-NEXT: ret i32 [[TRUNC]]
;
%xor = xor i64 %a, 1
Expand All @@ -36,8 +36,8 @@ define i32 @shrink_xor(i64 %a) {

define <2 x i32> @shrink_xor_vec(<2 x i64> %a) {
; CHECK-LABEL: @shrink_xor_vec(
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i64> %a, <i64 2, i64 2>
; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[XOR]] to <2 x i32>
; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i64> %a to <2 x i32>
; CHECK-NEXT: [[TRUNC:%.*]] = xor <2 x i32> [[TMP1]], <i32 2, i32 2>
; CHECK-NEXT: ret <2 x i32> [[TRUNC]]
;
%xor = xor <2 x i64> %a, <i64 2, i64 2>
Expand All @@ -49,8 +49,8 @@ define <2 x i32> @shrink_xor_vec(<2 x i64> %a) {

define i3 @shrink_or(i6 %a) {
; CHECK-LABEL: @shrink_or(
; CHECK-NEXT: [[OR:%.*]] = or i6 %a, 1
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i6 [[OR]] to i3
; CHECK-NEXT: [[TMP1:%.*]] = trunc i6 %a to i3
; CHECK-NEXT: [[TRUNC:%.*]] = or i3 [[TMP1]], 1
; CHECK-NEXT: ret i3 [[TRUNC]]
;
%or = or i6 %a, 33
Expand All @@ -62,16 +62,16 @@ define i3 @shrink_or(i6 %a) {

define <2 x i8> @shrink_or_vec(<2 x i16> %a) {
; CHECK-LABEL: @shrink_or_vec(
; CHECK-NEXT: [[OR:%.*]] = or <2 x i16> %a, <i16 -1, i16 256>
; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i16> [[OR]] to <2 x i8>
; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i16> %a to <2 x i8>
; CHECK-NEXT: [[TRUNC:%.*]] = or <2 x i8> [[TMP1]], <i8 -1, i8 0>
; CHECK-NEXT: ret <2 x i8> [[TRUNC]]
;
%or = or <2 x i16> %a, <i16 -1, i16 256>
%trunc = trunc <2 x i16> %or to <2 x i8>
ret <2 x i8> %trunc
}

; We discriminate against weird types?
; We discriminate against weird types.

define i31 @shrink_and(i64 %a) {
; CHECK-LABEL: @shrink_and(
Expand All @@ -88,8 +88,8 @@ define i31 @shrink_and(i64 %a) {

define <2 x i32> @shrink_and_vec(<2 x i33> %a) {
; CHECK-LABEL: @shrink_and_vec(
; CHECK-NEXT: [[AND:%.*]] = and <2 x i33> %a, <i33 -4294967296, i33 6>
; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i33> [[AND]] to <2 x i32>
; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i33> %a to <2 x i32>
; CHECK-NEXT: [[TRUNC:%.*]] = and <2 x i32> [[TMP1]], <i32 0, i32 6>
; CHECK-NEXT: ret <2 x i32> [[TRUNC]]
;
%and = and <2 x i33> %a, <i33 4294967296, i33 6>
Expand Down

0 comments on commit b34fe0f

Please sign in to comment.