Skip to content

Commit e359eaa

Browse files
committedNov 22, 2016
[InstCombine] change bitwise logic type to eliminate bitcasts
In PR27925: https://llvm.org/bugs/show_bug.cgi?id=27925 ...we proposed adding this fold to eliminate a bitcast. In D20774, there was some concern about changing the type of a bitwise op as well as creating bitcasts that might not be free for a target. However, if we're strictly eliminating an instruction (by limiting this to one-use ops), then we should be able to do this in InstCombine. But we're cautiously restricting the transform for now to vector types to avoid possible backend problems. A transform to make sure the logic op is legal for the target should be added to reverse this transform and improve codegen. Differential Revision: https://reviews.llvm.org/D26641 llvm-svn: 287707
1 parent eda365c commit e359eaa

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed
 

‎llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -1778,6 +1778,46 @@ static Instruction *canonicalizeBitCastExtElt(BitCastInst &BitCast,
17781778
return ExtractElementInst::Create(NewBC, ExtElt->getIndexOperand());
17791779
}
17801780

1781+
/// Change the type of a bitwise logic operation if we can eliminate a bitcast.
1782+
static Instruction *foldBitCastBitwiseLogic(BitCastInst &BitCast,
1783+
InstCombiner::BuilderTy &Builder) {
1784+
BinaryOperator *BO;
1785+
if (!match(BitCast.getOperand(0), m_OneUse(m_BinOp(BO))))
1786+
return nullptr;
1787+
1788+
auto Opcode = BO->getOpcode();
1789+
if (Opcode != Instruction::And && Opcode != Instruction::Or &&
1790+
Opcode != Instruction::Xor)
1791+
return nullptr;
1792+
1793+
Type *DestTy = BitCast.getType();
1794+
if (!DestTy->getScalarType()->isIntegerTy())
1795+
return nullptr;
1796+
1797+
// FIXME: This transform is restricted to vector types to avoid backend
1798+
// problems caused by creating potentially illegal operations. If a fix-up is
1799+
// added to handle that situation, we can remove this check.
1800+
if (!DestTy->isVectorTy() || !BO->getType()->isVectorTy())
1801+
return nullptr;
1802+
1803+
Value *X;
1804+
if (match(BO->getOperand(0), m_OneUse(m_BitCast(m_Value(X)))) &&
1805+
X->getType() == DestTy && !isa<Constant>(X)) {
1806+
// bitcast(logic(bitcast(X), Y)) --> logic'(X, bitcast(Y))
1807+
Value *CastedOp1 = Builder.CreateBitCast(BO->getOperand(1), DestTy);
1808+
return BinaryOperator::Create(Opcode, X, CastedOp1);
1809+
}
1810+
1811+
if (match(BO->getOperand(1), m_OneUse(m_BitCast(m_Value(X)))) &&
1812+
X->getType() == DestTy && !isa<Constant>(X)) {
1813+
// bitcast(logic(Y, bitcast(X))) --> logic'(bitcast(Y), X)
1814+
Value *CastedOp0 = Builder.CreateBitCast(BO->getOperand(0), DestTy);
1815+
return BinaryOperator::Create(Opcode, CastedOp0, X);
1816+
}
1817+
1818+
return nullptr;
1819+
}
1820+
17811821
/// Check if all users of CI are StoreInsts.
17821822
static bool hasStoreUsersOnly(CastInst &CI) {
17831823
for (User *U : CI.users()) {
@@ -2030,6 +2070,9 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) {
20302070
if (Instruction *I = canonicalizeBitCastExtElt(CI, *this, DL))
20312071
return I;
20322072

2073+
if (Instruction *I = foldBitCastBitwiseLogic(CI, *Builder))
2074+
return I;
2075+
20332076
if (SrcTy->isPointerTy())
20342077
return commonPointerCastTransforms(CI);
20352078
return commonCastTransforms(CI);

‎llvm/test/Transforms/InstCombine/bitcast.ll

+25-4
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,8 @@ define <2 x i32> @or_bitcast_int_to_vec(i64 %a) {
7474

7575
define <4 x i32> @bitcasts_and_bitcast(<4 x i32> %a, <8 x i16> %b) {
7676
; CHECK-LABEL: @bitcasts_and_bitcast(
77-
; CHECK-NEXT: [[BC1:%.*]] = bitcast <4 x i32> %a to <2 x i64>
78-
; CHECK-NEXT: [[BC2:%.*]] = bitcast <8 x i16> %b to <2 x i64>
79-
; CHECK-NEXT: [[AND:%.*]] = and <2 x i64> [[BC2]], [[BC1]]
80-
; CHECK-NEXT: [[BC3:%.*]] = bitcast <2 x i64> [[AND]] to <4 x i32>
77+
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> %b to <4 x i32>
78+
; CHECK-NEXT: [[BC3:%.*]] = and <4 x i32> [[TMP1]], %a
8179
; CHECK-NEXT: ret <4 x i32> [[BC3]]
8280
;
8381
%bc1 = bitcast <4 x i32> %a to <2 x i64>
@@ -87,6 +85,27 @@ define <4 x i32> @bitcasts_and_bitcast(<4 x i32> %a, <8 x i16> %b) {
8785
ret <4 x i32> %bc3
8886
}
8987

88+
; The destination must have an integer element type.
89+
; FIXME: We can still eliminate one bitcast in this test by doing the logic op
90+
; in the type of the input that has an integer element type.
91+
92+
define <4 x float> @bitcasts_and_bitcast_to_fp(<4 x float> %a, <8 x i16> %b) {
93+
; CHECK-LABEL: @bitcasts_and_bitcast_to_fp(
94+
; CHECK-NEXT: [[BC1:%.*]] = bitcast <4 x float> %a to <2 x i64>
95+
; CHECK-NEXT: [[BC2:%.*]] = bitcast <8 x i16> %b to <2 x i64>
96+
; CHECK-NEXT: [[AND:%.*]] = and <2 x i64> [[BC2]], [[BC1]]
97+
; CHECK-NEXT: [[BC3:%.*]] = bitcast <2 x i64> [[AND]] to <4 x float>
98+
; CHECK-NEXT: ret <4 x float> [[BC3]]
99+
;
100+
%bc1 = bitcast <4 x float> %a to <2 x i64>
101+
%bc2 = bitcast <8 x i16> %b to <2 x i64>
102+
%and = and <2 x i64> %bc2, %bc1
103+
%bc3 = bitcast <2 x i64> %and to <4 x float>
104+
ret <4 x float> %bc3
105+
}
106+
107+
; FIXME: Transform limited from changing vector op to integer op to avoid codegen problems.
108+
90109
define i128 @bitcast_or_bitcast(i128 %a, <2 x i64> %b) {
91110
; CHECK-LABEL: @bitcast_or_bitcast(
92111
; CHECK-NEXT: [[BC1:%.*]] = bitcast i128 %a to <2 x i64>
@@ -100,6 +119,8 @@ define i128 @bitcast_or_bitcast(i128 %a, <2 x i64> %b) {
100119
ret i128 %bc2
101120
}
102121

122+
; FIXME: Transform limited from changing integer op to vector op to avoid codegen problems.
123+
103124
define <4 x i32> @bitcast_xor_bitcast(<4 x i32> %a, i128 %b) {
104125
; CHECK-LABEL: @bitcast_xor_bitcast(
105126
; CHECK-NEXT: [[BC1:%.*]] = bitcast <4 x i32> %a to i128

0 commit comments

Comments
 (0)
Please sign in to comment.