Skip to content

Commit 180a6b0

Browse files
LegNeatoFirestar99
authored andcommitted
Optimize num_traits::Float::powi to use GLSL.std.450 Pow
Fixes #516.
1 parent eb79ff7 commit 180a6b0

File tree

5 files changed

+43
-0
lines changed

5 files changed

+43
-0
lines changed

crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub enum LibmCustomIntrinsic {
3030
Tgamma,
3131
Log1p,
3232
NextAfter,
33+
Powi,
3334
Remainder,
3435
RemQuo,
3536
Scalbn,
@@ -157,6 +158,7 @@ pub const TABLE: &[(&str, LibmIntrinsic)] = &[
157158
),
158159
("pow", LibmIntrinsic::GLOp(GLOp::Pow)),
159160
("powf", LibmIntrinsic::GLOp(GLOp::Pow)),
161+
("powi", LibmIntrinsic::Custom(LibmCustomIntrinsic::Powi)),
160162
(
161163
"remainder",
162164
LibmIntrinsic::Custom(LibmCustomIntrinsic::Remainder),
@@ -306,6 +308,12 @@ impl Builder<'_, '_> {
306308
LibmIntrinsic::Custom(LibmCustomIntrinsic::NextAfter) => {
307309
self.undef_zombie(result_type, "NextAfter not supported yet")
308310
}
311+
LibmIntrinsic::Custom(LibmCustomIntrinsic::Powi) => {
312+
assert_eq!(args.len(), 2);
313+
// Convert integer exponent to float, then use GLOp::Pow
314+
let float_exp = self.sitofp(args[1], args[0].ty);
315+
self.gl_op(GLOp::Pow, result_type, [args[0], float_exp])
316+
}
309317
LibmIntrinsic::Custom(LibmCustomIntrinsic::Remainder) => {
310318
self.undef_zombie(result_type, "Remainder not supported yet")
311319
}

crates/rustc_codegen_spirv/src/codegen_cx/declare.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,14 @@ impl<'tcx> CodegenCx<'tcx> {
166166
}
167167
}
168168

169+
// Check for usage of `num_traits` intrinsics (like Float::powi) that we can optimize
170+
if self.tcx.crate_name(def_id.krate) == self.sym.num_traits && !def_id.is_local() {
171+
let item_name = self.tcx.item_name(def_id);
172+
if let Some(&intrinsic) = self.sym.libm_intrinsics.get(&item_name) {
173+
self.libm_intrinsics.borrow_mut().insert(def_id, intrinsic);
174+
}
175+
}
176+
169177
// Check if this is a From trait implementation
170178
if let Some(impl_def_id) = self.tcx.impl_of_method(def_id)
171179
&& let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id)

crates/rustc_codegen_spirv/src/symbols.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub struct Symbols {
1818
pub vector: Symbol,
1919
pub v1: Symbol,
2020
pub libm: Symbol,
21+
pub num_traits: Symbol,
2122
pub entry_point_name: Symbol,
2223
pub spv_khr_vulkan_memory_model: Symbol,
2324

@@ -416,6 +417,7 @@ impl Symbols {
416417
vector: Symbol::intern("vector"),
417418
v1: Symbol::intern("v1"),
418419
libm: Symbol::intern("libm"),
420+
num_traits: Symbol::intern("num_traits"),
419421
entry_point_name: Symbol::intern("entry_point_name"),
420422
spv_khr_vulkan_memory_model: Symbol::intern("SPV_KHR_vulkan_memory_model"),
421423

tests/compiletests/ui/dis/powi.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Test that `Float::powi` uses GLSL.std.450 Pow instead of a loop-based implementation.
2+
// See https://github.com/Rust-GPU/rust-gpu/issues/516
3+
4+
// build-pass
5+
// compile-flags: -C llvm-args=--disassemble-entry=main
6+
7+
use spirv_std::num_traits::Float;
8+
use spirv_std::spirv;
9+
10+
#[spirv(fragment)]
11+
pub fn main(input: f32, output: &mut f32) {
12+
*output = input.powi(2);
13+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
%1 = OpFunction %2 None %3
2+
%4 = OpLabel
3+
OpLine %5 11 12
4+
%6 = OpLoad %7 %8
5+
OpLine %5 12 20
6+
%9 = OpConvertSToF %7 %10
7+
%11 = OpExtInst %7 %12 26 %6 %9
8+
OpLine %5 12 4
9+
OpStore %13 %11
10+
OpNoLine
11+
OpReturn
12+
OpFunctionEnd

0 commit comments

Comments
 (0)