1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

[AArch64] Fix useful bits detection for BFM instructions

Summary:
When computing useful bits for a BFM instruction, we need
to take into consideration the case where both operands
of the BFM are equal and provide data that we need to track.

Not doing this can cause us to miss useful bits.
    
Fixes PR31138 (https://llvm.org/bugs/show_bug.cgi?id=31138)

Reviewers: t.p.northover, jmolloy

Subscribers: evandro, gberry, srhines, pirama, mcrosier, aemerson, llvm-commits, rengolin

Differential Revision: https://reviews.llvm.org/D27130

llvm-svn: 288253
This commit is contained in:
Silviu Baranga 2016-11-30 17:04:22 +00:00
parent 30f006473b
commit eb3c226087
2 changed files with 68 additions and 9 deletions

View File

@ -1875,23 +1875,52 @@ static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits,
uint64_t MSB =
cast<const ConstantSDNode>(Op.getOperand(3).getNode())->getZExtValue();
if (Op.getOperand(1) == Orig)
return getUsefulBitsFromBitfieldMoveOpd(Op, UsefulBits, Imm, MSB, Depth);
APInt OpUsefulBits(UsefulBits);
OpUsefulBits = 1;
APInt ResultUsefulBits(UsefulBits.getBitWidth(), 0);
ResultUsefulBits.flipAllBits();
APInt Mask(UsefulBits.getBitWidth(), 0);
getUsefulBits(Op, ResultUsefulBits, Depth + 1);
if (MSB >= Imm) {
OpUsefulBits = OpUsefulBits.shl(MSB - Imm + 1);
// The instruction is a BFXIL.
uint64_t Width = MSB - Imm + 1;
uint64_t LSB = Imm;
OpUsefulBits = OpUsefulBits.shl(Width);
--OpUsefulBits;
UsefulBits &= ~OpUsefulBits;
getUsefulBits(Op, UsefulBits, Depth + 1);
} else {
OpUsefulBits = OpUsefulBits.shl(MSB + 1);
--OpUsefulBits;
UsefulBits = ~(OpUsefulBits.shl(OpUsefulBits.getBitWidth() - Imm));
getUsefulBits(Op, UsefulBits, Depth + 1);
if (Op.getOperand(1) == Orig) {
// Copy the low bits from the result to bits starting from LSB.
Mask = ResultUsefulBits & OpUsefulBits;
Mask = Mask.shl(LSB);
}
if (Op.getOperand(0) == Orig)
// Bits starting from LSB in the input contribute to the result.
Mask |= (ResultUsefulBits & ~OpUsefulBits);
} else {
// The instruction is a BFI.
uint64_t Width = MSB + 1;
uint64_t LSB = UsefulBits.getBitWidth() - Imm;
OpUsefulBits = OpUsefulBits.shl(Width);
--OpUsefulBits;
OpUsefulBits = OpUsefulBits.shl(LSB);
if (Op.getOperand(1) == Orig) {
// Copy the bits from the result to the zero bits.
Mask = ResultUsefulBits & OpUsefulBits;
Mask = Mask.lshr(LSB);
}
if (Op.getOperand(0) == Orig)
Mask |= (ResultUsefulBits & ~OpUsefulBits);
}
UsefulBits &= Mask;
}
static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits,

View File

@ -530,3 +530,33 @@ define i16 @test_ignored_rightbits(i32 %dst, i32 %in) {
ret i16 %conv19
}
; The following test excercises the case where we have a BFI
; instruction with the same input in both operands. We need to
; track the useful bits through both operands.
; CHECK-LABEL: sameOperandBFI
; CHECK: lsr
; CHECK: and
; CHECK: bfi
; CHECK: bfi
define void @sameOperandBFI(i64 %src, i64 %src2, i16 *%ptr) {
entry:
%shr47 = lshr i64 %src, 47
%src2.trunc = trunc i64 %src2 to i32
br i1 undef, label %end, label %if.else
if.else:
%and3 = and i32 %src2.trunc, 3
%shl2 = shl nuw nsw i64 %shr47, 2
%shl2.trunc = trunc i64 %shl2 to i32
%and12 = and i32 %shl2.trunc, 12
%BFISource = or i32 %and3, %and12 ; ...00000ABCD
%BFIRHS = shl nuw nsw i32 %BFISource, 4 ; ...0ABCD0000
%BFI = or i32 %BFIRHS, %BFISource ; ...0ABCDABCD
%BFItrunc = trunc i32 %BFI to i16
store i16 %BFItrunc, i16* %ptr, align 4
br label %end
end:
ret void
}