Skip to content

Commit e6382f2

Browse files
authored
SelectionDAG: neg (and x, 1) --> SIGN_EXTEND_INREG x, i1 (llvm#131239)
The pattern ```LLVM %shl = shl i32 %x, 31 %ashr = ashr i32 %shl, 31 ``` would be combined to `SIGN_EXTEND_INREG %x, ValueType:ch:i1` by SelectionDAG. However InstCombine normalizes this pattern to: ```LLVM %and = and i32 %x, 1 %neg = sub i32 0, %and ``` This adds matching code to DAGCombiner to catch this variant as well.
1 parent 3fcd921 commit e6382f2

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3964,6 +3964,20 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
39643964
isNullConstant(N1S.getOperand(0)))
39653965
return DAG.getSplat(VT, DL, N1S.getOperand(1));
39663966
}
3967+
3968+
// sub 0, (and x, 1) --> SIGN_EXTEND_INREG x, i1
3969+
if (N1.getOpcode() == ISD::AND && N1.hasOneUse() &&
3970+
isOneOrOneSplat(N1->getOperand(1))) {
3971+
EVT ExtVT = EVT::getIntegerVT(*DAG.getContext(), 1);
3972+
if (VT.isVector())
3973+
ExtVT = EVT::getVectorVT(*DAG.getContext(), ExtVT,
3974+
VT.getVectorElementCount());
3975+
if (TLI.getOperationAction(ISD::SIGN_EXTEND_INREG, ExtVT) ==
3976+
TargetLowering::Legal) {
3977+
return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, N1->getOperand(0),
3978+
DAG.getValueType(ExtVT));
3979+
}
3980+
}
39673981
}
39683982

39693983
// Canonicalize (sub -1, x) -> ~x, i.e. (xor x, -1)

llvm/test/CodeGen/AArch64/arm64-bitfield-extract.ll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,3 +1067,18 @@ if.else:
10671067
end:
10681068
ret void
10691069
}
1070+
1071+
define i64 @sign_extend_lsb(i64 %arg) nounwind {
1072+
; LLC-LABEL: sign_extend_lsb:
1073+
; LLC: // %bb.0:
1074+
; LLC-NEXT: sbfx x0, x0, #0, #1
1075+
; LLC-NEXT: ret
1076+
; OPT-LABEL: @sign_extend_lsb(
1077+
; OPT-NEXT: [[AND:%.*]] = and i64 [[ARG:%.*]], 1
1078+
; OPT-NEXT: [[NEG:%.*]] = sub i64 0, [[AND]]
1079+
; OPT-NEXT: ret i64 [[NEG]]
1080+
;
1081+
%and = and i64 %arg, 1
1082+
%neg = sub i64 0, %and
1083+
ret i64 %neg
1084+
}

llvm/test/CodeGen/AArch64/pr61111.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ define i62 @f(i1 %0) {
55
; CHECK-LABEL: f:
66
; CHECK: // %bb.0:
77
; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
8-
; CHECK-NEXT: and x8, x0, #0x1
9-
; CHECK-NEXT: sub x8, x8, #1
10-
; CHECK-NEXT: tst x8, #0x3fffffffffffffff
8+
; CHECK-NEXT: sbfx x8, x0, #0, #1
9+
; CHECK-NEXT: mov x9, #4611686018427387903 // =0x3fffffffffffffff
10+
; CHECK-NEXT: bics xzr, x9, x8
1111
; CHECK-NEXT: cset w0, ne
1212
; CHECK-NEXT: ret
1313
%2 = zext i1 %0 to i59

0 commit comments

Comments
 (0)