Skip to content

Commit 708a6ee

Browse files
committed
[DAGCombiner] Add basic support for trunc nsw/nuw
1 parent a64ac3f commit 708a6ee

File tree

5 files changed

+59
-65
lines changed

5 files changed

+59
-65
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2330,6 +2330,8 @@ static bool isTruncateOf(SelectionDAG &DAG, SDValue N, SDValue &Op,
23302330
if (N->getOpcode() == ISD::TRUNCATE) {
23312331
Op = N->getOperand(0);
23322332
Known = DAG.computeKnownBits(Op);
2333+
if (N->getFlags().hasNoUnsignedWrap())
2334+
Known.Zero.setBitsFrom(N.getScalarValueSizeInBits());
23332335
return true;
23342336
}
23352337

@@ -13889,23 +13891,22 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
1388913891
unsigned OpBits = Op.getScalarValueSizeInBits();
1389013892
unsigned MidBits = N0.getScalarValueSizeInBits();
1389113893
unsigned DestBits = VT.getScalarSizeInBits();
13892-
unsigned NumSignBits = DAG.ComputeNumSignBits(Op);
1389313894

13894-
if (OpBits == DestBits) {
13895-
// Op is i32, Mid is i8, and Dest is i32. If Op has more than 24 sign
13896-
// bits, it is already ready.
13897-
if (NumSignBits > DestBits-MidBits)
13895+
if (N0->getFlags().hasNoSignedWrap() ||
13896+
DAG.ComputeNumSignBits(Op) > OpBits - MidBits) {
13897+
if (OpBits == DestBits) {
13898+
// Op is i32, Mid is i8, and Dest is i32. If Op has more than 24 sign
13899+
// bits, it is already ready.
1389813900
return Op;
13899-
} else if (OpBits < DestBits) {
13900-
// Op is i32, Mid is i8, and Dest is i64. If Op has more than 24 sign
13901-
// bits, just sext from i32.
13902-
if (NumSignBits > OpBits-MidBits)
13901+
} else if (OpBits < DestBits) {
13902+
// Op is i32, Mid is i8, and Dest is i64. If Op has more than 24 sign
13903+
// bits, just sext from i32.
1390313904
return DAG.getNode(ISD::SIGN_EXTEND, DL, VT, Op);
13904-
} else {
13905-
// Op is i64, Mid is i8, and Dest is i32. If Op has more than 56 sign
13906-
// bits, just truncate to i32.
13907-
if (NumSignBits > OpBits-MidBits)
13905+
} else {
13906+
// Op is i64, Mid is i8, and Dest is i32. If Op has more than 56 sign
13907+
// bits, just truncate to i32.
1390813908
return DAG.getNode(ISD::TRUNCATE, DL, VT, Op);
13909+
}
1390913910
}
1391013911

1391113912
// fold (sext (truncate x)) -> (sextinreg x).
@@ -14176,24 +14177,23 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
1417614177
unsigned OpBits = SrcVT.getScalarSizeInBits();
1417714178
unsigned MidBits = MinVT.getScalarSizeInBits();
1417814179
unsigned DestBits = VT.getScalarSizeInBits();
14179-
unsigned NumSignBits = DAG.ComputeNumSignBits(Op);
1418014180

14181-
if (OpBits == DestBits) {
14182-
// Op is i32, Mid is i8, and Dest is i32. If Op has more than 24 sign
14183-
// bits, it is already ready.
14184-
if (NumSignBits > DestBits - MidBits)
14181+
if (N0->getFlags().hasNoSignedWrap() ||
14182+
DAG.ComputeNumSignBits(Op) > OpBits - MidBits) {
14183+
if (OpBits == DestBits) {
14184+
// Op is i32, Mid is i8, and Dest is i32. If Op has more than 24 sign
14185+
// bits, it is already ready.
1418514186
return Op;
14186-
} else if (OpBits < DestBits) {
14187-
// Op is i32, Mid is i8, and Dest is i64. If Op has more than 24 sign
14188-
// bits, just sext from i32.
14189-
// FIXME: This can probably be ZERO_EXTEND nneg?
14190-
if (NumSignBits > OpBits - MidBits)
14187+
} else if (OpBits < DestBits) {
14188+
// Op is i32, Mid is i8, and Dest is i64. If Op has more than 24 sign
14189+
// bits, just sext from i32.
14190+
// FIXME: This can probably be ZERO_EXTEND nneg?
1419114191
return DAG.getNode(ISD::SIGN_EXTEND, DL, VT, Op);
14192-
} else {
14193-
// Op is i64, Mid is i8, and Dest is i32. If Op has more than 56 sign
14194-
// bits, just truncate to i32.
14195-
if (NumSignBits > OpBits - MidBits)
14192+
} else {
14193+
// Op is i64, Mid is i8, and Dest is i32. If Op has more than 56 sign
14194+
// bits, just truncate to i32.
1419614195
return DAG.getNode(ISD::TRUNCATE, DL, VT, Op);
14196+
}
1419714197
}
1419814198
}
1419914199

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3826,7 +3826,13 @@ void SelectionDAGBuilder::visitTrunc(const User &I) {
38263826
SDValue N = getValue(I.getOperand(0));
38273827
EVT DestVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
38283828
I.getType());
3829-
setValue(&I, DAG.getNode(ISD::TRUNCATE, getCurSDLoc(), DestVT, N));
3829+
SDNodeFlags Flags;
3830+
if (auto *Trunc = dyn_cast<TruncInst>(&I)) {
3831+
Flags.setNoSignedWrap(Trunc->hasNoSignedWrap());
3832+
Flags.setNoUnsignedWrap(Trunc->hasNoUnsignedWrap());
3833+
}
3834+
3835+
setValue(&I, DAG.getNode(ISD::TRUNCATE, getCurSDLoc(), DestVT, N, Flags));
38303836
}
38313837

38323838
void SelectionDAGBuilder::visitZExt(const User &I) {

llvm/test/CodeGen/AArch64/trunc-nsw-nuw.ll

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ define zeroext i32 @trunc_nuw_nsw_urem(i64 %x) nounwind {
55
; CHECK-LABEL: trunc_nuw_nsw_urem:
66
; CHECK: // %bb.0: // %entry
77
; CHECK-NEXT: mov w8, #5977 // =0x1759
8-
; CHECK-NEXT: mov w9, w0
9-
; CHECK-NEXT: movk w8, #53687, lsl #16
10-
; CHECK-NEXT: umull x8, w9, w8
118
; CHECK-NEXT: mov w9, #10000 // =0x2710
9+
; CHECK-NEXT: movk w8, #53687, lsl #16
10+
; CHECK-NEXT: mul x8, x0, x8
1211
; CHECK-NEXT: lsr x8, x8, #45
1312
; CHECK-NEXT: msub w0, w8, w9, w0
1413
; CHECK-NEXT: ret
@@ -22,8 +21,7 @@ define i64 @zext_nneg_udiv_trunc_nuw(i64 %x) nounwind {
2221
; CHECK-LABEL: zext_nneg_udiv_trunc_nuw:
2322
; CHECK: // %bb.0: // %entry
2423
; CHECK-NEXT: mov w8, #52429 // =0xcccd
25-
; CHECK-NEXT: and w9, w0, #0xffff
26-
; CHECK-NEXT: mul w8, w9, w8
24+
; CHECK-NEXT: mul w8, w0, w8
2725
; CHECK-NEXT: lsr w0, w8, #23
2826
; CHECK-NEXT: ret
2927
entry:
@@ -37,8 +35,7 @@ define i64 @sext_udiv_trunc_nuw(i64 %x) nounwind {
3735
; CHECK-LABEL: sext_udiv_trunc_nuw:
3836
; CHECK: // %bb.0: // %entry
3937
; CHECK-NEXT: mov w8, #52429 // =0xcccd
40-
; CHECK-NEXT: and w9, w0, #0xffff
41-
; CHECK-NEXT: mul w8, w9, w8
38+
; CHECK-NEXT: mul w8, w0, w8
4239
; CHECK-NEXT: lsr w0, w8, #23
4340
; CHECK-NEXT: ret
4441
entry:

llvm/test/CodeGen/RISCV/trunc-nsw-nuw.ll

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
define signext i8 @trunc_nsw_add(i32 signext %x) nounwind {
55
; CHECK-LABEL: trunc_nsw_add:
66
; CHECK: # %bb.0: # %entry
7-
; CHECK-NEXT: addi a0, a0, 1
8-
; CHECK-NEXT: slli a0, a0, 56
9-
; CHECK-NEXT: srai a0, a0, 56
7+
; CHECK-NEXT: addiw a0, a0, 1
108
; CHECK-NEXT: ret
119
entry:
1210
%add = add nsw i32 %x, 1
@@ -17,11 +15,11 @@ entry:
1715
define signext i32 @trunc_nuw_nsw_urem(i64 %x) nounwind {
1816
; CHECK-LABEL: trunc_nuw_nsw_urem:
1917
; CHECK: # %bb.0: # %entry
20-
; CHECK-NEXT: slli a1, a0, 32
21-
; CHECK-NEXT: lui a2, 858993
22-
; CHECK-NEXT: addi a2, a2, 1881
23-
; CHECK-NEXT: slli a2, a2, 32
24-
; CHECK-NEXT: mulhu a1, a1, a2
18+
; CHECK-NEXT: lui a1, 210
19+
; CHECK-NEXT: addiw a1, a1, -1167
20+
; CHECK-NEXT: slli a1, a1, 12
21+
; CHECK-NEXT: addi a1, a1, 1881
22+
; CHECK-NEXT: mul a1, a0, a1
2523
; CHECK-NEXT: srli a1, a1, 45
2624
; CHECK-NEXT: lui a2, 2
2725
; CHECK-NEXT: addi a2, a2, 1808
@@ -37,11 +35,10 @@ entry:
3735
define i64 @zext_nneg_udiv_trunc_nuw(i64 %x) nounwind {
3836
; CHECK-LABEL: zext_nneg_udiv_trunc_nuw:
3937
; CHECK: # %bb.0: # %entry
40-
; CHECK-NEXT: lui a1, 52429
41-
; CHECK-NEXT: slli a1, a1, 4
42-
; CHECK-NEXT: slli a0, a0, 48
43-
; CHECK-NEXT: mulhu a0, a0, a1
44-
; CHECK-NEXT: srli a0, a0, 23
38+
; CHECK-NEXT: lui a1, 13
39+
; CHECK-NEXT: addi a1, a1, -819
40+
; CHECK-NEXT: mul a0, a0, a1
41+
; CHECK-NEXT: srliw a0, a0, 23
4542
; CHECK-NEXT: ret
4643
entry:
4744
%trunc = trunc nuw i64 %x to i16
@@ -53,11 +50,10 @@ entry:
5350
define i64 @sext_udiv_trunc_nuw(i64 %x) nounwind {
5451
; CHECK-LABEL: sext_udiv_trunc_nuw:
5552
; CHECK: # %bb.0: # %entry
56-
; CHECK-NEXT: lui a1, 52429
57-
; CHECK-NEXT: slli a1, a1, 4
58-
; CHECK-NEXT: slli a0, a0, 48
59-
; CHECK-NEXT: mulhu a0, a0, a1
60-
; CHECK-NEXT: srli a0, a0, 23
53+
; CHECK-NEXT: lui a1, 13
54+
; CHECK-NEXT: addi a1, a1, -819
55+
; CHECK-NEXT: mul a0, a0, a1
56+
; CHECK-NEXT: srliw a0, a0, 23
6157
; CHECK-NEXT: ret
6258
entry:
6359
%trunc = trunc nuw i64 %x to i16
@@ -69,7 +65,6 @@ entry:
6965
define ptr @gep_nusw_zext_nneg_add_trunc_nuw_nsw(ptr %p, i64 %x) nounwind {
7066
; CHECK-LABEL: gep_nusw_zext_nneg_add_trunc_nuw_nsw:
7167
; CHECK: # %bb.0: # %entry
72-
; CHECK-NEXT: sext.w a1, a1
7368
; CHECK-NEXT: slli a1, a1, 2
7469
; CHECK-NEXT: add a0, a1, a0
7570
; CHECK-NEXT: addi a0, a0, 20

llvm/test/CodeGen/X86/trunc-nsw-nuw.ll

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ define zeroext i32 @trunc_nuw_nsw_urem(i64 %x) nounwind {
55
; CHECK-LABEL: trunc_nuw_nsw_urem:
66
; CHECK: # %bb.0: # %entry
77
; CHECK-NEXT: movq %rdi, %rax
8-
; CHECK-NEXT: movl %eax, %ecx
9-
; CHECK-NEXT: movl $3518437209, %edx # imm = 0xD1B71759
10-
; CHECK-NEXT: imulq %rcx, %rdx
11-
; CHECK-NEXT: shrq $45, %rdx
12-
; CHECK-NEXT: imull $10000, %edx, %ecx # imm = 0x2710
8+
; CHECK-NEXT: movl $3518437209, %ecx # imm = 0xD1B71759
9+
; CHECK-NEXT: imulq %rdi, %rcx
10+
; CHECK-NEXT: shrq $45, %rcx
11+
; CHECK-NEXT: imull $10000, %ecx, %ecx # imm = 0x2710
1312
; CHECK-NEXT: subl %ecx, %eax
1413
; CHECK-NEXT: # kill: def $eax killed $eax killed $rax
1514
; CHECK-NEXT: retq
@@ -22,8 +21,7 @@ entry:
2221
define i64 @zext_nneg_udiv_trunc_nuw(i64 %x) nounwind {
2322
; CHECK-LABEL: zext_nneg_udiv_trunc_nuw:
2423
; CHECK: # %bb.0: # %entry
25-
; CHECK-NEXT: movzwl %di, %eax
26-
; CHECK-NEXT: imull $52429, %eax, %eax # imm = 0xCCCD
24+
; CHECK-NEXT: imull $52429, %edi, %eax # imm = 0xCCCD
2725
; CHECK-NEXT: shrl $23, %eax
2826
; CHECK-NEXT: retq
2927
entry:
@@ -36,8 +34,7 @@ entry:
3634
define i64 @sext_udiv_trunc_nuw(i64 %x) nounwind {
3735
; CHECK-LABEL: sext_udiv_trunc_nuw:
3836
; CHECK: # %bb.0: # %entry
39-
; CHECK-NEXT: movzwl %di, %eax
40-
; CHECK-NEXT: imull $52429, %eax, %eax # imm = 0xCCCD
37+
; CHECK-NEXT: imull $52429, %edi, %eax # imm = 0xCCCD
4138
; CHECK-NEXT: shrl $23, %eax
4239
; CHECK-NEXT: retq
4340
entry:
@@ -50,8 +47,7 @@ entry:
5047
define ptr @gep_nusw_zext_nneg_add_trunc_nuw_nsw(ptr %p, i64 %x) nounwind {
5148
; CHECK-LABEL: gep_nusw_zext_nneg_add_trunc_nuw_nsw:
5249
; CHECK: # %bb.0: # %entry
53-
; CHECK-NEXT: movl %esi, %eax
54-
; CHECK-NEXT: leaq 20(%rdi,%rax,4), %rax
50+
; CHECK-NEXT: leaq 20(%rdi,%rsi,4), %rax
5551
; CHECK-NEXT: retq
5652
entry:
5753
%trunc = trunc nuw nsw i64 %x to i32

0 commit comments

Comments
 (0)