Skip to content

Commit ef7aed3

Browse files
committed
[InstCombine] Do not fold 'and (sext (ashr X, Shift)), C' if Shift < 0
The 'and (sext (ashr X, ShiftC)), C' --> 'lshr (sext X), ShiftC' transformation would access out of bounds bits in APInt::getLowBitsSet if the shift count was larger than X's bit width or if it was negative. Fixes llvm#56424
1 parent 6656029 commit ef7aed3

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1808,7 +1808,8 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
18081808

18091809
unsigned Width = Ty->getScalarSizeInBits();
18101810
const APInt *ShiftC;
1811-
if (match(Op0, m_OneUse(m_SExt(m_AShr(m_Value(X), m_APInt(ShiftC)))))) {
1811+
if (match(Op0, m_OneUse(m_SExt(m_AShr(m_Value(X), m_APInt(ShiftC))))) &&
1812+
ShiftC->ult(Width)) {
18121813
if (*C == APInt::getLowBitsSet(Width, Width - ShiftC->getZExtValue())) {
18131814
// We are clearing high bits that were potentially set by sext+ashr:
18141815
// and (sext (ashr X, ShiftC)), C --> lshr (sext X), ShiftC
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s --passes=instcombine -S | FileCheck %s
3+
4+
; This would crash if we didn't check for a negative shift.
5+
; https://github.com/llvm/llvm-project/issues/56424
6+
define i64 @PR56424(i1 %cond, i32 %arg) {
7+
; CHECK-LABEL: @PR56424(
8+
; CHECK-NEXT: entry:
9+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
10+
; CHECK: if.then:
11+
; CHECK-NEXT: br label [[IF_END]]
12+
; CHECK: if.end:
13+
; CHECK-NEXT: ret i64 0
14+
;
15+
entry:
16+
br i1 %cond, label %if.then, label %if.end
17+
18+
if.then:
19+
%shr = ashr i32 %arg, -2
20+
%sext = sext i32 %shr to i64
21+
br label %if.end
22+
23+
if.end:
24+
%val = phi i64 [ %sext, %if.then ], [ 0, %entry ]
25+
%and = and i64 -81, %val
26+
ret i64 %and
27+
}

0 commit comments

Comments
 (0)