[llvm] LoopIdiom/test: add negative tests for fpowi (PR #68985)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 13 05:55:57 PDT 2023
https://github.com/artagnon created https://github.com/llvm/llvm-project/pull/68985
Compiling the following program under -ffast-math results in very poor codegen due to LoopVectorize:
```c
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.
>From 573a6e2cd4689057cf4075d97e4ae5bd364380d1 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <Ramkumar.Ramachandra at imgtec.com>
Date: Fri, 13 Oct 2023 13:43:30 +0100
Subject: [PATCH] LoopIdiom/test: add negative tests for fpowi
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/test/Transforms/LoopIdiom/fpowi.ll | 122 ++++++++++++++++++++++++
1 file changed, 122 insertions(+)
create mode 100644 llvm/test/Transforms/LoopIdiom/fpowi.ll
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
+}
More information about the llvm-commits
mailing list