From 3da115a93b782796e3d267266b4241e5258f1fef Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 5 Mar 2023 20:19:41 -0800 Subject: Add+Use `mir::BinOp::Cmp` --- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 30 +++++++++++++++++++++++++ compiler/rustc_codegen_ssa/src/traits/consts.rs | 1 + 2 files changed, 31 insertions(+) (limited to 'compiler/rustc_codegen_ssa') diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 0e8c4abf212..f0933fe33d7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -7,6 +7,7 @@ use crate::common::{self, IntPredicate}; use crate::traits::*; use crate::MemFlags; +use rustc_hir as hir; use rustc_middle::mir; use rustc_middle::mir::Operand; use rustc_middle::ty::cast::{CastTy, IntTy}; @@ -882,6 +883,35 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.icmp(base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed), lhs, rhs) } } + mir::BinOp::Cmp => { + use std::cmp::Ordering; + debug_assert!(!is_float); + let pred = |op| base::bin_op_to_icmp_predicate(op, is_signed); + if bx.cx().tcx().sess.opts.optimize == OptLevel::No { + // FIXME: This actually generates tighter assembly, and is a classic trick + // + // However, as of 2023-11 it optimizes worse in things like derived + // `PartialOrd`, so only use it in debug for now. Once LLVM can handle it + // better (see ), it'll + // be worth trying it in optimized builds as well. + let is_gt = bx.icmp(pred(hir::BinOpKind::Gt), lhs, rhs); + let gtext = bx.zext(is_gt, bx.type_i8()); + let is_lt = bx.icmp(pred(hir::BinOpKind::Lt), lhs, rhs); + let ltext = bx.zext(is_lt, bx.type_i8()); + bx.unchecked_ssub(gtext, ltext) + } else { + // These operations are those expected by `tests/codegen/integer-cmp.rs`, + // from . + let is_lt = bx.icmp(pred(hir::BinOpKind::Lt), lhs, rhs); + let is_ne = bx.icmp(pred(hir::BinOpKind::Ne), lhs, rhs); + let ge = bx.select( + is_ne, + bx.cx().const_i8(Ordering::Greater as i8), + bx.cx().const_i8(Ordering::Equal as i8), + ); + bx.select(is_lt, bx.cx().const_i8(Ordering::Less as i8), ge) + } + } } } diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index 4dff9c7684f..8cb17a5b37a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -19,6 +19,7 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_bool(&self, val: bool) -> Self::Value; fn const_i16(&self, i: i16) -> Self::Value; fn const_i32(&self, i: i32) -> Self::Value; + fn const_i8(&self, i: i8) -> Self::Value; fn const_u32(&self, i: u32) -> Self::Value; fn const_u64(&self, i: u64) -> Self::Value; fn const_u128(&self, i: u128) -> Self::Value; -- cgit 1.4.1-3-g733a5