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);
+
+ 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 {
- OpUsefulBits = OpUsefulBits.shl(MSB + 1);
+ // The instruction is a BFI.
+ uint64_t Width = MSB + 1;
+ uint64_t LSB = UsefulBits.getBitWidth() - Imm;
+
+ OpUsefulBits = OpUsefulBits.shl(Width);
--OpUsefulBits;
- UsefulBits = ~(OpUsefulBits.shl(OpUsefulBits.getBitWidth() - Imm));
- getUsefulBits(Op, UsefulBits, Depth + 1);
+ 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,
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
+}