-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LoopIdiom/test: add negative tests for fpowi #68985
Conversation
Compiling the following program under -ffast-math results in very poor codegen due to LoopVectorize: float fpowi(float base, int exp) { float result = 1.0; while (exp != 0) { result *= base; --exp; } return result; } In preparation to get LoopIdiomRecognize to convert this idiom to a llvm.powi, add negative tests corresponding to variations of this program.
@llvm/pr-subscribers-llvm-transforms Author: Ramkumar Ramachandra (artagnon) ChangesCompiling the following program under -ffast-math results in very poor codegen due to LoopVectorize: float fpowi(float base, int exp) {
float result = 1.0;
while (exp != 0) {
result *= base;
--exp;
}
return result;
} In preparation to get LoopIdiomRecognize to convert this idiom to a llvm.powi, add negative tests corresponding to variations of this program. Full diff: https://github.com/llvm/llvm-project/pull/68985.diff 1 Files Affected:
diff --git a/llvm/test/Transforms/LoopIdiom/fpowi.ll b/llvm/test/Transforms/LoopIdiom/fpowi.ll
new file mode 100644
index 000000000000000..640921cb8c367f3
--- /dev/null
+++ b/llvm/test/Transforms/LoopIdiom/fpowi.ll
@@ -0,0 +1,122 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=loop-idiom < %s -S | FileCheck %s
+
+; TODO: Currently, LIR doesn't recognize the fpowi idiom, but it could in the
+; future, generating llvm.powi intrinsics for the positive tests.
+
+define float @fpowi_f32(float %base, i32 %exp) {
+; CHECK-LABEL: @fpowi_f32(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[EXP:%.*]], 0
+; CHECK-NEXT: br i1 [[CMP_NOT]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; CHECK: while.body.preheader:
+; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
+; CHECK: while.body:
+; CHECK-NEXT: [[RESULT:%.*]] = phi float [ [[MUL:%.*]], [[WHILE_BODY]] ], [ 1.000000e+00, [[WHILE_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[MERGE_DEC:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[EXP]], [[WHILE_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[MUL]] = fmul fast float [[RESULT]], [[BASE:%.*]]
+; CHECK-NEXT: [[DEC]] = add nsw i32 [[MERGE_DEC]], -1
+; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[DEC]], 0
+; CHECK-NEXT: br i1 [[CMP_EQ]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; CHECK: while.end.loopexit:
+; CHECK-NEXT: [[MUL_LCSSA:%.*]] = phi float [ [[MUL]], [[WHILE_BODY]] ]
+; CHECK-NEXT: br label [[WHILE_END]]
+; CHECK: while.end:
+; CHECK-NEXT: [[RESULT_LCSSA:%.*]] = phi float [ 1.000000e+00, [[ENTRY:%.*]] ], [ [[MUL_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; CHECK-NEXT: ret float [[RESULT_LCSSA]]
+;
+entry:
+ %cmp.not = icmp eq i32 %exp, 0
+ br i1 %cmp.not, label %while.end, label %while.body
+
+while.body: ; preds = %entry, %while.body
+ %result = phi float [ %mul, %while.body ], [ 1.000000e+00, %entry ]
+ %merge.dec = phi i32 [ %dec, %while.body ], [ %exp, %entry ]
+ %mul = fmul fast float %result, %base
+ %dec = add nsw i32 %merge.dec, -1
+ %cmp.eq = icmp eq i32 %dec, 0
+ br i1 %cmp.eq, label %while.end, label %while.body
+
+while.end: ; preds = %while.body, %entry
+ %result.lcssa = phi float [ 1.000000e+00, %entry ], [ %mul, %while.body ]
+ ret float %result.lcssa
+}
+
+define double @fpowi_f64(double %base, i32 %exp) {
+; CHECK-LABEL: @fpowi_f64(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[EXP:%.*]], 0
+; CHECK-NEXT: br i1 [[CMP_NOT]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; CHECK: while.body.preheader:
+; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
+; CHECK: while.body:
+; CHECK-NEXT: [[RESULT:%.*]] = phi double [ [[MUL:%.*]], [[WHILE_BODY]] ], [ 1.000000e+00, [[WHILE_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[MERGE_DEC:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[EXP]], [[WHILE_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[MUL]] = fmul fast double [[RESULT]], [[BASE:%.*]]
+; CHECK-NEXT: [[DEC]] = add nsw i32 [[MERGE_DEC]], -1
+; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[DEC]], 0
+; CHECK-NEXT: br i1 [[CMP_EQ]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; CHECK: while.end.loopexit:
+; CHECK-NEXT: [[MUL_LCSSA:%.*]] = phi double [ [[MUL]], [[WHILE_BODY]] ]
+; CHECK-NEXT: br label [[WHILE_END]]
+; CHECK: while.end:
+; CHECK-NEXT: [[RESULT_LCSSA:%.*]] = phi double [ 1.000000e+00, [[ENTRY:%.*]] ], [ [[MUL_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; CHECK-NEXT: ret double [[RESULT_LCSSA]]
+;
+entry:
+ %cmp.not = icmp eq i32 %exp, 0
+ br i1 %cmp.not, label %while.end, label %while.body
+
+while.body: ; preds = %entry, %while.body
+ %result = phi double [ %mul, %while.body ], [ 1.000000e+00, %entry ]
+ %merge.dec = phi i32 [ %dec, %while.body ], [ %exp, %entry ]
+ %mul = fmul fast double %result, %base
+ %dec = add nsw i32 %merge.dec, -1
+ %cmp.eq = icmp eq i32 %dec, 0
+ br i1 %cmp.eq, label %while.end, label %while.body
+
+while.end: ; preds = %while.body, %entry
+ %result.lcssa = phi double [ 1.000000e+00, %entry ], [ %mul, %while.body ]
+ ret double %result.lcssa
+}
+
+; Negative tests
+
+; The loop idiom is only legal in -ffast-math mode
+define float @fpowi_nofast(float %base, i32 %exp) {
+; CHECK-LABEL: @fpowi_nofast(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[EXP:%.*]], 0
+; CHECK-NEXT: br i1 [[CMP_NOT]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; CHECK: while.body.preheader:
+; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
+; CHECK: while.body:
+; CHECK-NEXT: [[RESULT:%.*]] = phi float [ [[MUL:%.*]], [[WHILE_BODY]] ], [ 1.000000e+00, [[WHILE_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[MERGE_DEC:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[EXP]], [[WHILE_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[MUL]] = fmul float [[RESULT]], [[BASE:%.*]]
+; CHECK-NEXT: [[DEC]] = add nsw i32 [[MERGE_DEC]], -1
+; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[DEC]], 0
+; CHECK-NEXT: br i1 [[CMP_EQ]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; CHECK: while.end.loopexit:
+; CHECK-NEXT: [[MUL_LCSSA:%.*]] = phi float [ [[MUL]], [[WHILE_BODY]] ]
+; CHECK-NEXT: br label [[WHILE_END]]
+; CHECK: while.end:
+; CHECK-NEXT: [[RESULT_LCSSA:%.*]] = phi float [ 1.000000e+00, [[ENTRY:%.*]] ], [ [[MUL_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; CHECK-NEXT: ret float [[RESULT_LCSSA]]
+;
+entry:
+ %cmp.not = icmp eq i32 %exp, 0
+ br i1 %cmp.not, label %while.end, label %while.body
+
+while.body: ; preds = %entry, %while.body
+ %result = phi float [ %mul, %while.body ], [ 1.000000e+00, %entry ]
+ %merge.dec = phi i32 [ %dec, %while.body ], [ %exp, %entry ]
+ %mul = fmul float %result, %base
+ %dec = add nsw i32 %merge.dec, -1
+ %cmp.eq = icmp eq i32 %dec, 0
+ br i1 %cmp.eq, label %while.end, label %while.body
+
+while.end: ; preds = %while.body, %entry
+ %result.lcssa = phi float [ 1.000000e+00, %entry ], [ %mul, %while.body ]
+ ret float %result.lcssa
+}
|
What are we supposed to do for negative exp value? |
Will open a new PR, once I've finished implementing the idiom in LIR. |
Compiling the following program under -ffast-math results in very poor codegen due to LoopVectorize:
In preparation to get LoopIdiomRecognize to convert this idiom to a llvm.powi, add negative tests corresponding to variations of this program.