Skip to content

Commit aafaa2f

Browse files
committed
[SCCP] convert ashr to lshr for non-negative shift value
This is similar to the existing signed instruction folds. We get the obvious minimal patterns in other passes, but this avoids potential missed folds when the multi-block tests are converted to selects.
1 parent 204a2ff commit aafaa2f

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

llvm/lib/Transforms/Scalar/SCCP.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ static bool replaceSignedInst(SCCPSolver &Solver,
181181
NewInst = new ZExtInst(Op0, Inst.getType(), "", &Inst);
182182
break;
183183
}
184+
case Instruction::AShr: {
185+
// If the shifted value is not negative, this is a logical shift right.
186+
Value *Op0 = Inst.getOperand(0);
187+
if (InsertedValues.count(Op0) || !isNonNegative(Op0))
188+
return false;
189+
NewInst = BinaryOperator::CreateLShr(Op0, Inst.getOperand(1), "", &Inst);
190+
break;
191+
}
184192
case Instruction::SDiv:
185193
case Instruction::SRem: {
186194
// If both operands are not negative, this is the same as udiv/urem.

llvm/test/Transforms/SCCP/ashr.ll

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
define i8 @ashr_and(i8 %x) {
55
; CHECK-LABEL: @ashr_and(
66
; CHECK-NEXT: [[PX:%.*]] = and i8 [[X:%.*]], 127
7-
; CHECK-NEXT: [[R:%.*]] = ashr i8 [[PX]], 1
7+
; CHECK-NEXT: [[R:%.*]] = lshr i8 [[PX]], 1
88
; CHECK-NEXT: ret i8 [[R]]
99
;
1010
%px = and i8 %x, 127
@@ -14,7 +14,7 @@ define i8 @ashr_and(i8 %x) {
1414

1515
define i8 @ashr_const(i8 %x) {
1616
; CHECK-LABEL: @ashr_const(
17-
; CHECK-NEXT: [[R:%.*]] = ashr i8 42, [[X:%.*]]
17+
; CHECK-NEXT: [[R:%.*]] = lshr i8 42, [[X:%.*]]
1818
; CHECK-NEXT: ret i8 [[R]]
1919
;
2020
%r = ashr i8 42, %x
@@ -24,14 +24,16 @@ define i8 @ashr_const(i8 %x) {
2424
define i8 @ashr_zext(i7 %x, i8 %y) {
2525
; CHECK-LABEL: @ashr_zext(
2626
; CHECK-NEXT: [[PX:%.*]] = zext i7 [[X:%.*]] to i8
27-
; CHECK-NEXT: [[R:%.*]] = ashr i8 [[PX]], [[Y:%.*]]
27+
; CHECK-NEXT: [[R:%.*]] = lshr i8 [[PX]], [[Y:%.*]]
2828
; CHECK-NEXT: ret i8 [[R]]
2929
;
3030
%px = zext i7 %x to i8
3131
%r = ashr i8 %px, %y
3232
ret i8 %r
3333
}
3434

35+
; negative test
36+
3537
define i8 @ashr_not_nonneg(i7 %x, i8 %y) {
3638
; CHECK-LABEL: @ashr_not_nonneg(
3739
; CHECK-NEXT: [[PX:%.*]] = sext i7 [[X:%.*]] to i8
@@ -51,7 +53,7 @@ define i32 @dominating_condition(i32 %x) {
5153
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
5254
; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
5355
; CHECK: t:
54-
; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X]], 16
56+
; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X]], 16
5557
; CHECK-NEXT: br label [[EXIT:%.*]]
5658
; CHECK: f:
5759
; CHECK-NEXT: br label [[EXIT]]
@@ -85,7 +87,7 @@ define i32 @dominating_condition_alt(i32 %x, i32 %y) {
8587
; CHECK: t:
8688
; CHECK-NEXT: br label [[EXIT:%.*]]
8789
; CHECK: f:
88-
; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X]], [[Y:%.*]]
90+
; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X]], [[Y:%.*]]
8991
; CHECK-NEXT: br label [[EXIT]]
9092
; CHECK: exit:
9193
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ -42, [[T]] ], [ [[A]], [[F]] ]

0 commit comments

Comments
 (0)