Skip to content

Commit 71f56e4

Browse files
authored
[ConstraintElim] Decompose shl nsw for signed predicates (#76961)
shl nsw x, shift can be interpreted as mul nsw x, (1<<shift), except when shift is bw-1 (https://alive2.llvm.org/ce/z/vDh2xT). Use this when decomposing shl. The equivalent decomposition for the unsigned case already exists.
1 parent b662c9a commit 71f56e4

File tree

2 files changed

+49
-6
lines changed

2 files changed

+49
-6
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,18 @@ static Decomposition decompose(Value *V,
517517
return Result;
518518
}
519519

520+
// (shl nsw x, shift) is (mul nsw x, (1<<shift)), with the exception of
521+
// shift == bw-1.
522+
if (match(V, m_NSWShl(m_Value(Op0), m_ConstantInt(CI)))) {
523+
uint64_t Shift = CI->getValue().getLimitedValue();
524+
if (Shift < Ty->getIntegerBitWidth() - 1) {
525+
assert(Shift < 64 && "Would overflow");
526+
auto Result = decompose(Op0, Preconditions, IsSigned, DL);
527+
Result.mul(int64_t(1) << Shift);
528+
return Result;
529+
}
530+
}
531+
520532
return V;
521533
}
522534

llvm/test/Transforms/ConstraintElimination/shl.ll

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,8 +1283,7 @@ define i1 @shl_nsw_x8_slt_x7(i8 %start, i8 %high) {
12831283
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i8 [[START_SHL_3]], [[HIGH]]
12841284
; CHECK-NEXT: call void @llvm.assume(i1 [[C_1]])
12851285
; CHECK-NEXT: [[START_MUL_7:%.*]] = mul nsw i8 [[START]], 7
1286-
; CHECK-NEXT: [[T_1:%.*]] = icmp slt i8 [[START_MUL_7]], [[HIGH]]
1287-
; CHECK-NEXT: ret i1 [[T_1]]
1286+
; CHECK-NEXT: ret i1 true
12881287
;
12891288
%c.0 = icmp sge i8 %high, 0
12901289
call void @llvm.assume(i1 %c.0)
@@ -1327,11 +1326,9 @@ define i1 @shl_nsw_sign_implication(i8 %x) {
13271326
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[X]], 0
13281327
; CHECK-NEXT: br i1 [[CMP1]], label [[IF:%.*]], label [[ELSE:%.*]]
13291328
; CHECK: if:
1330-
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[SHL]], 0
1331-
; CHECK-NEXT: ret i1 [[CMP2]]
1329+
; CHECK-NEXT: ret i1 true
13321330
; CHECK: else:
1333-
; CHECK-NEXT: [[CMP3:%.*]] = icmp sge i8 [[SHL]], 0
1334-
; CHECK-NEXT: ret i1 [[CMP3]]
1331+
; CHECK-NEXT: ret i1 true
13351332
;
13361333
%shl = shl nsw i8 %x, 2
13371334
%cmp1 = icmp slt i8 %x, 0
@@ -1361,3 +1358,37 @@ define i1 @shl_nsw_by_bw_minus_1(i64 %x) {
13611358
%t.1 = icmp slt i64 %x, 0
13621359
ret i1 %t.1
13631360
}
1361+
1362+
; Shift returns poison in this case, just make sure we don't crash.
1363+
define i1 @shl_nsw_by_bw(i64 %x) {
1364+
; CHECK-LABEL: @shl_nsw_by_bw(
1365+
; CHECK-NEXT: [[X_SHL:%.*]] = shl nsw i64 [[X:%.*]], 64
1366+
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[X_SHL]], 0
1367+
; CHECK-NEXT: call void @llvm.assume(i1 [[C_1]])
1368+
; CHECK-NEXT: [[T_1:%.*]] = icmp slt i64 [[X]], 0
1369+
; CHECK-NEXT: ret i1 [[T_1]]
1370+
;
1371+
%x.shl = shl nsw i64 %x, 64
1372+
%c.1 = icmp slt i64 %x.shl, 0
1373+
call void @llvm.assume(i1 %c.1)
1374+
1375+
%t.1 = icmp slt i64 %x, 0
1376+
ret i1 %t.1
1377+
}
1378+
1379+
; Shift returns poison in this case, just make sure we don't crash.
1380+
define i1 @shl_nsw_by_bw_plus_1(i64 %x) {
1381+
; CHECK-LABEL: @shl_nsw_by_bw_plus_1(
1382+
; CHECK-NEXT: [[X_SHL:%.*]] = shl nsw i64 [[X:%.*]], 65
1383+
; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[X_SHL]], 0
1384+
; CHECK-NEXT: call void @llvm.assume(i1 [[C_1]])
1385+
; CHECK-NEXT: [[T_1:%.*]] = icmp slt i64 [[X]], 0
1386+
; CHECK-NEXT: ret i1 [[T_1]]
1387+
;
1388+
%x.shl = shl nsw i64 %x, 65
1389+
%c.1 = icmp slt i64 %x.shl, 0
1390+
call void @llvm.assume(i1 %c.1)
1391+
1392+
%t.1 = icmp slt i64 %x, 0
1393+
ret i1 %t.1
1394+
}

0 commit comments

Comments
 (0)