Skip to content

Commit 4423e80

Browse files
committed
[InstCombine] Add restrict for the operands of fmul
According the discussion, except the fmul itself, all its operands should also have reassoc flag.
1 parent 1f93f62 commit 4423e80

File tree

2 files changed

+65
-21
lines changed

2 files changed

+65
-21
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,17 @@ Instruction *InstCombinerImpl::foldFPSignBitOps(BinaryOperator &I) {
573573

574574
Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) {
575575
Value *X, *Y, *Z;
576+
577+
// Make sure all operands have reassoc flag if they are powi.
578+
if (!all_of(I.operands(), [](Value *V) {
579+
if (match(V, m_Intrinsic<Intrinsic::powi>(m_Value(), m_Value()))) {
580+
Instruction *Powi = cast<Instruction>(V);
581+
return Powi->hasAllowReassoc();
582+
}
583+
return true;
584+
}))
585+
return nullptr;
586+
576587
auto createPowiExpr = [](BinaryOperator &I, InstCombinerImpl &IC, Value *X,
577588
Value *Y, Value *Z) {
578589
Value *YZ;

llvm/test/Transforms/InstCombine/powi.ll

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -125,22 +125,55 @@ entry:
125125
ret double %mul
126126
}
127127

128-
define double @powi_fmul_powi_no_reassoc(double %x, i32 %y, i32 %z) {
129-
; CHECK-LABEL: @powi_fmul_powi_no_reassoc(
128+
; Negative test: Missing reassoc flag on fmul
129+
define double @powi_fmul_powi_no_reassoc1(double %x, i32 %y, i32 %z) {
130+
; CHECK-LABEL: @powi_fmul_powi_no_reassoc1(
130131
; CHECK-NEXT: entry:
131-
; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
132-
; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])
132+
; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
133+
; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])
133134
; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P2]], [[P1]]
134135
; CHECK-NEXT: ret double [[MUL]]
135136
;
136137
entry:
137-
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
138-
%p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z)
138+
%p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
139+
%p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
139140
%mul = fmul double %p2, %p1
140141
ret double %mul
141142
}
142143

144+
; Negative test: Missing reassoc flag on 2nd operand
145+
define double @powi_fmul_powi_no_reassoc2(double %x, i32 %y, i32 %z) {
146+
; CHECK-LABEL: @powi_fmul_powi_no_reassoc2(
147+
; CHECK-NEXT: entry:
148+
; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
149+
; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])
150+
; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]
151+
; CHECK-NEXT: ret double [[MUL]]
152+
;
153+
entry:
154+
%p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
155+
%p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z)
156+
%mul = fmul reassoc double %p2, %p1
157+
ret double %mul
158+
}
159+
160+
; Negative test: Missing reassoc flag on 1st operand
161+
define double @powi_fmul_powi_no_reassoc3(double %x, i32 %y, i32 %z) {
162+
; CHECK-LABEL: @powi_fmul_powi_no_reassoc3(
163+
; CHECK-NEXT: entry:
164+
; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
165+
; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])
166+
; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]
167+
; CHECK-NEXT: ret double [[MUL]]
168+
;
169+
entry:
170+
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
171+
%p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
172+
%mul = fmul reassoc double %p2, %p1
173+
ret double %mul
174+
}
143175

176+
; All of the fmul and its operands should have the reassoc flags
144177
define double @powi_fmul_powi(double %x, i32 %y, i32 %z) {
145178
; CHECK-LABEL: @powi_fmul_powi(
146179
; CHECK-NEXT: entry:
@@ -149,8 +182,8 @@ define double @powi_fmul_powi(double %x, i32 %y, i32 %z) {
149182
; CHECK-NEXT: ret double [[MUL]]
150183
;
151184
entry:
152-
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
153-
%p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z)
185+
%p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
186+
%p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
154187
%mul = fmul reassoc double %p2, %p1
155188
ret double %mul
156189
}
@@ -163,8 +196,8 @@ define double @powi_fmul_powi_fast_on_fmul(double %x, i32 %y, i32 %z) {
163196
; CHECK-NEXT: ret double [[MUL]]
164197
;
165198
entry:
166-
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
167-
%p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z)
199+
%p1 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %y)
200+
%p2 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %z)
168201
%mul = fmul fast double %p2, %p1
169202
ret double %mul
170203
}
@@ -192,42 +225,42 @@ define double @powi_fmul_powi_same_power(double %x, i32 %y, i32 %z) {
192225
; CHECK-NEXT: ret double [[MUL]]
193226
;
194227
entry:
195-
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
196-
%p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
228+
%p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
229+
%p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
197230
%mul = fmul reassoc double %p2, %p1
198231
ret double %mul
199232
}
200233

201234
define double @powi_fmul_powi_use_first(double %x, i32 %y, i32 %z) {
202235
; CHECK-LABEL: @powi_fmul_powi_use_first(
203236
; CHECK-NEXT: entry:
204-
; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
237+
; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
205238
; CHECK-NEXT: tail call void @use(double [[P1]])
206239
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Y]], [[Z:%.*]]
207240
; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[TMP0]])
208241
; CHECK-NEXT: ret double [[MUL]]
209242
;
210243
entry:
211-
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
244+
%p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
212245
tail call void @use(double %p1)
213-
%p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z)
246+
%p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
214247
%mul = fmul reassoc double %p1, %p2
215248
ret double %mul
216249
}
217250

218251
define double @powi_fmul_powi_use_second(double %x, i32 %y, i32 %z) {
219252
; CHECK-LABEL: @powi_fmul_powi_use_second(
220253
; CHECK-NEXT: entry:
221-
; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Z:%.*]])
254+
; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Z:%.*]])
222255
; CHECK-NEXT: tail call void @use(double [[P1]])
223256
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Y:%.*]], [[Z]]
224257
; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[TMP0]])
225258
; CHECK-NEXT: ret double [[MUL]]
226259
;
227260
entry:
228-
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %z)
261+
%p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
229262
tail call void @use(double %p1)
230-
%p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
263+
%p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
231264
%mul = fmul reassoc double %p2, %p1
232265
ret double %mul
233266
}
@@ -333,11 +366,11 @@ define double @fdiv_pow_powi_negative(double %x) {
333366
; Negative test: The 2nd powi argument is a variable
334367
define double @fdiv_pow_powi_negative_variable(double %x, i32 %y) {
335368
; CHECK-LABEL: @fdiv_pow_powi_negative_variable(
336-
; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
369+
; CHECK-NEXT: [[P1:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
337370
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[X]]
338371
; CHECK-NEXT: ret double [[DIV]]
339372
;
340-
%p1 = call double @llvm.powi.f64.i32(double %x, i32 %y)
373+
%p1 = call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
341374
%div = fdiv reassoc nnan double %p1, %x
342375
ret double %div
343376
}
@@ -348,7 +381,7 @@ define double @powi_fmul_powi_x(double noundef %x) {
348381
; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
349382
; CHECK-NEXT: ret double [[MUL]]
350383
;
351-
%p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3)
384+
%p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 3)
352385
%mul = fmul reassoc double %p1, %x
353386
ret double %mul
354387
}

0 commit comments

Comments
 (0)