================
@@ -11177,6 +11177,40 @@ std::pair<SDValue, uint64_t>
lookThroughSignExtension(SDValue Val) {
return {Val, Val.getValueSizeInBits() - 1};
}
+// Op is an SDValue that is being compared to 0. If the comparison is a bit
+// test, optimize it to a TBZ or TBNZ.
+static SDValue optimizeBitTest(SDValue Op, SDValue Chain, SDValue Dest,
+ unsigned Opcode, SelectionDAG &DAG) {
+ SDLoc DL(Op);
+
+ if (Op.getOpcode() != ISD::AND)
+ return SDValue();
+
+ // See if we can use a TBZ to fold in an AND as well.
+ // TBZ has a smaller branch displacement than CBZ. If the offset is
+ // out of bounds, a late MI-layer pass rewrites branches.
+ // 403.gcc is an example that hits this case.
+ if (isa<ConstantSDNode>(Op.getOperand(1)) &&
+ isPowerOf2_64(Op.getConstantOperandVal(1))) {
+ SDValue Test = Op.getOperand(0);
+ uint64_t Mask = Op.getConstantOperandVal(1);
+ return DAG.getNode(Opcode, DL, MVT::Other, Chain, Test,
+ DAG.getConstant(Log2_64(Mask), DL, MVT::i64), Dest);
+ }
+
+ if (Op.getOperand(0).getOpcode() == ISD::SHL) {
----------------
pcc wrote:
Yes, the code would stay the same size with the check for a single use of the
shift. Checking for a single use of the AND could theoretically save one
instruction, but it seems like an uncommon code pattern; in stage2 clang it
only changed the code size of about 15 functions and more often than not led to
increased code size because of something that a later pass did. So I don't
think it's worth adding any use checks here.
https://github.com/llvm/llvm-project/pull/172962
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits