Skip to content

Commit 55c6d91

Browse files
authored
[InstCombine] Preserve nuw/nsw/exact flags when transforming (C shift (A add nuw C1)) --> ((C shift C1) shift A). (#79490)
If we weren't shifting out any non-zero bits or changing the sign before the transform, we shouldn't be after. Alive2: https://alive2.llvm.org/ce/z/mB-rWz
1 parent d2c8167 commit 55c6d91

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,14 @@ Instruction *InstCombinerImpl::commonShiftTransforms(BinaryOperator &I) {
439439
if (match(Op0, m_Constant(C)) &&
440440
match(Op1, m_NUWAdd(m_Value(A), m_Constant(C1)))) {
441441
Value *NewC = Builder.CreateBinOp(I.getOpcode(), C, C1);
442-
return BinaryOperator::Create(I.getOpcode(), NewC, A);
442+
BinaryOperator *NewShiftOp = BinaryOperator::Create(I.getOpcode(), NewC, A);
443+
if (I.getOpcode() == Instruction::Shl) {
444+
NewShiftOp->setHasNoSignedWrap(I.hasNoSignedWrap());
445+
NewShiftOp->setHasNoUnsignedWrap(I.hasNoUnsignedWrap());
446+
} else {
447+
NewShiftOp->setIsExact(I.isExact());
448+
}
449+
return NewShiftOp;
443450
}
444451

445452
unsigned BitWidth = Ty->getScalarSizeInBits();

llvm/test/Transforms/InstCombine/shift-add.ll

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,48 @@ define i32 @ashr_add_nuw(i32 %x, ptr %p) {
159159
ret i32 %r
160160
}
161161

162+
; Preserve nuw and exact flags.
163+
164+
define i32 @shl_nuw_add_nuw(i32 %x) {
165+
; CHECK-LABEL: @shl_nuw_add_nuw(
166+
; CHECK-NEXT: [[R:%.*]] = shl nuw i32 2, [[X:%.*]]
167+
; CHECK-NEXT: ret i32 [[R]]
168+
;
169+
%a = add nuw i32 %x, 1
170+
%r = shl nuw i32 1, %a
171+
ret i32 %r
172+
}
173+
174+
define i32 @shl_nsw_add_nuw(i32 %x) {
175+
; CHECK-LABEL: @shl_nsw_add_nuw(
176+
; CHECK-NEXT: [[R:%.*]] = shl nsw i32 -2, [[X:%.*]]
177+
; CHECK-NEXT: ret i32 [[R]]
178+
;
179+
%a = add nuw i32 %x, 1
180+
%r = shl nsw i32 -1, %a
181+
ret i32 %r
182+
}
183+
184+
define i32 @lshr_exact_add_nuw(i32 %x) {
185+
; CHECK-LABEL: @lshr_exact_add_nuw(
186+
; CHECK-NEXT: [[R:%.*]] = lshr exact i32 2, [[X:%.*]]
187+
; CHECK-NEXT: ret i32 [[R]]
188+
;
189+
%a = add nuw i32 %x, 1
190+
%r = lshr exact i32 4, %a
191+
ret i32 %r
192+
}
193+
194+
define i32 @ashr_exact_add_nuw(i32 %x) {
195+
; CHECK-LABEL: @ashr_exact_add_nuw(
196+
; CHECK-NEXT: [[R:%.*]] = ashr exact i32 -2, [[X:%.*]]
197+
; CHECK-NEXT: ret i32 [[R]]
198+
;
199+
%a = add nuw i32 %x, 1
200+
%r = ashr exact i32 -4, %a
201+
ret i32 %r
202+
}
203+
162204
; negative test - must have 'nuw'
163205

164206
define i32 @shl_add_nsw(i32 %x) {

0 commit comments

Comments
 (0)