-
Notifications
You must be signed in to change notification settings - Fork 14.3k
SelectionDAG: neg (and x, 1) --> SIGN_EXTEND_INREG x, i1 #131239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The pattern %shl = shl i32 %x, 31 %ashr = ashr i32 %shl, 31 can be combined to SIGN_EXTEND_INREG %x, ValueType:ch:i1 However InstCombine normalizes this pattern to the equivalent %and = and i32 %x, 1 %neg = sub i32 0, %and This adds a DAGCombiner pattern to still turn this into SIGN_EXTEND_INREG.
@llvm/pr-subscribers-llvm-selectiondag @llvm/pr-subscribers-backend-aarch64 Author: Matthias Braun (MatzeB) ChangesThe pattern %shl = shl i32 %x, 31
%ashr = ashr i32 %shl, 31 is combined to %and = and i32 %x, 1
%neg = sub i32 0, %and Add a pattern to DAGCombiner to catch this variant too. Full diff: https://github.com/llvm/llvm-project/pull/131239.diff 3 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c35838601cc9c..a54857e1037e2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -3964,6 +3964,20 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
isNullConstant(N1S.getOperand(0)))
return DAG.getSplat(VT, DL, N1S.getOperand(1));
}
+
+ // sub 0, (and x, 1) --> SIGN_EXTEND_INREG x, i1
+ if (N1.getOpcode() == ISD::AND && N1.hasOneUse() &&
+ isOneOrOneSplat(N1->getOperand(1))) {
+ EVT ExtVT = EVT::getIntegerVT(*DAG.getContext(), 1);
+ if (VT.isVector())
+ ExtVT = EVT::getVectorVT(*DAG.getContext(), ExtVT,
+ VT.getVectorElementCount());
+ if (TLI.getOperationAction(ISD::SIGN_EXTEND_INREG, ExtVT) ==
+ TargetLowering::Legal) {
+ return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, N1->getOperand(0),
+ DAG.getValueType(ExtVT));
+ }
+ }
}
// Canonicalize (sub -1, x) -> ~x, i.e. (xor x, -1)
diff --git a/llvm/test/CodeGen/AArch64/arm64-bitfield-extract.ll b/llvm/test/CodeGen/AArch64/arm64-bitfield-extract.ll
index 9c8c34558d776..62ff4bbcc9c27 100644
--- a/llvm/test/CodeGen/AArch64/arm64-bitfield-extract.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-bitfield-extract.ll
@@ -1067,3 +1067,18 @@ if.else:
end:
ret void
}
+
+define i64 @sign_extend_lsb(i64 %arg) nounwind {
+; LLC-LABEL: sign_extend_lsb:
+; LLC: // %bb.0:
+; LLC-NEXT: sbfx x0, x0, #0, #1
+; LLC-NEXT: ret
+; OPT-LABEL: @sign_extend_lsb(
+; OPT-NEXT: [[AND:%.*]] = and i64 [[ARG:%.*]], 1
+; OPT-NEXT: [[NEG:%.*]] = sub i64 0, [[AND]]
+; OPT-NEXT: ret i64 [[NEG]]
+;
+ %and = and i64 %arg, 1
+ %neg = sub i64 0, %and
+ ret i64 %neg
+}
diff --git a/llvm/test/CodeGen/AArch64/pr61111.ll b/llvm/test/CodeGen/AArch64/pr61111.ll
index d2c72921a9229..be7c5981332e7 100644
--- a/llvm/test/CodeGen/AArch64/pr61111.ll
+++ b/llvm/test/CodeGen/AArch64/pr61111.ll
@@ -5,9 +5,9 @@ define i62 @f(i1 %0) {
; CHECK-LABEL: f:
; CHECK: // %bb.0:
; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
-; CHECK-NEXT: and x8, x0, #0x1
-; CHECK-NEXT: sub x8, x8, #1
-; CHECK-NEXT: tst x8, #0x3fffffffffffffff
+; CHECK-NEXT: sbfx x8, x0, #0, #1
+; CHECK-NEXT: mov x9, #4611686018427387903 // =0x3fffffffffffffff
+; CHECK-NEXT: bics xzr, x9, x8
; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
%2 = zext i1 %0 to i59
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
GlobalISel version of this combine is in #131367 |
The pattern
would be combined to
SIGN_EXTEND_INREG %x, ValueType:ch:i1
by SelectionDAG.However InstCombine normalizes this pattern to:
This adds matching code to DAGCombiner to catch this variant as well.