Skip to content

Commit 4224a36

Browse files
committed
[InstCombine] avoid creating an extra instruction in zext fold and possible inf-loop
The structure of this fold is suspect vs. most of instcombine because it creates instructions and tries to delete them immediately after. If we don't have the operand types for the icmps, then we are not behaving as assumed. And as shown in PR49475, we can inf-loop.
1 parent 78b8ce4 commit 4224a36

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,7 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &CI) {
12701270
ICmpInst *LHS = dyn_cast<ICmpInst>(SrcI->getOperand(0));
12711271
ICmpInst *RHS = dyn_cast<ICmpInst>(SrcI->getOperand(1));
12721272
if (LHS && RHS && LHS->hasOneUse() && RHS->hasOneUse() &&
1273+
LHS->getOperand(0)->getType() == RHS->getOperand(0)->getType() &&
12731274
(transformZExtICmp(LHS, CI, false) ||
12741275
transformZExtICmp(RHS, CI, false))) {
12751276
// zext (or icmp, icmp) -> or (zext icmp), (zext icmp)

llvm/test/Transforms/InstCombine/zext-or-icmp.ll

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,16 @@ block2:
101101
ret i32 %conv2
102102
}
103103

104-
; FIXME: This should not end with more instructions than it started from.
104+
; This should not end with more instructions than it started from.
105105

106106
define i32 @PR49475(i32 %x, i16 %y) {
107107
; CHECK-LABEL: @PR49475(
108108
; CHECK-NEXT: [[M:%.*]] = and i16 [[Y:%.*]], 1
109109
; CHECK-NEXT: [[B1:%.*]] = icmp eq i32 [[X:%.*]], 0
110-
; CHECK-NEXT: [[B11:%.*]] = zext i1 [[B1]] to i32
111-
; CHECK-NEXT: [[TMP1:%.*]] = xor i16 [[M]], 1
112-
; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[TMP1]] to i32
113-
; CHECK-NEXT: [[Z3:%.*]] = or i32 [[B11]], [[TMP2]]
114-
; CHECK-NEXT: ret i32 [[Z3]]
110+
; CHECK-NEXT: [[B2:%.*]] = icmp eq i16 [[M]], 0
111+
; CHECK-NEXT: [[T1:%.*]] = or i1 [[B1]], [[B2]]
112+
; CHECK-NEXT: [[Z:%.*]] = zext i1 [[T1]] to i32
113+
; CHECK-NEXT: ret i32 [[Z]]
115114
;
116115
%m = and i16 %y, 1
117116
%b1 = icmp eq i32 %x, 0
@@ -120,3 +119,50 @@ define i32 @PR49475(i32 %x, i16 %y) {
120119
%z = zext i1 %t1 to i32
121120
ret i32 %z
122121
}
122+
123+
; This would infinite-loop.
124+
125+
define i8 @PR49475_infloop(i32 %t0, i16 %insert, i64 %e, i8 %i162) {
126+
; CHECK-LABEL: @PR49475_infloop(
127+
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[T0:%.*]], 0
128+
; CHECK-NEXT: [[B2:%.*]] = icmp eq i16 [[INSERT:%.*]], 0
129+
; CHECK-NEXT: [[T1:%.*]] = or i1 [[B]], [[B2]]
130+
; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[T1]] to i32
131+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[EXT]], [[T0]]
132+
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], 140
133+
; CHECK-NEXT: [[XOR1:%.*]] = zext i32 [[TMP1]] to i64
134+
; CHECK-NEXT: [[CONV16:%.*]] = sext i8 [[I162:%.*]] to i64
135+
; CHECK-NEXT: [[SUB17:%.*]] = sub i64 [[CONV16]], [[E:%.*]]
136+
; CHECK-NEXT: [[SEXT:%.*]] = shl i64 [[SUB17]], 32
137+
; CHECK-NEXT: [[CONV18:%.*]] = ashr exact i64 [[SEXT]], 32
138+
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV18]], [[XOR1]]
139+
; CHECK-NEXT: [[CONV19:%.*]] = zext i1 [[CMP]] to i16
140+
; CHECK-NEXT: [[OR21:%.*]] = or i16 [[CONV19]], [[INSERT]]
141+
; CHECK-NEXT: [[TRUNC44:%.*]] = trunc i16 [[OR21]] to i8
142+
; CHECK-NEXT: [[INC:%.*]] = or i8 [[TRUNC44]], [[I162]]
143+
; CHECK-NEXT: [[TOBOOL23_NOT:%.*]] = icmp eq i16 [[OR21]], 0
144+
; CHECK-NEXT: call void @llvm.assume(i1 [[TOBOOL23_NOT]])
145+
; CHECK-NEXT: ret i8 [[INC]]
146+
;
147+
%b = icmp eq i32 %t0, 0
148+
%b2 = icmp eq i16 %insert, 0
149+
%t1 = or i1 %b, %b2
150+
%ext = zext i1 %t1 to i32
151+
%and = and i32 %t0, %ext
152+
%conv13 = zext i32 %and to i64
153+
%xor = xor i64 %conv13, 140
154+
%conv16 = sext i8 %i162 to i64
155+
%sub17 = sub i64 %conv16, %e
156+
%sext = shl i64 %sub17, 32
157+
%conv18 = ashr exact i64 %sext, 32
158+
%cmp = icmp sge i64 %xor, %conv18
159+
%conv19 = zext i1 %cmp to i16
160+
%or21 = or i16 %insert, %conv19
161+
%trunc44 = trunc i16 %or21 to i8
162+
%inc = add i8 %i162, %trunc44
163+
%tobool23.not = icmp eq i16 %or21, 0
164+
call void @llvm.assume(i1 %tobool23.not)
165+
ret i8 %inc
166+
}
167+
168+
declare void @llvm.assume(i1 noundef)

0 commit comments

Comments
 (0)