Skip to content

Commit

Permalink
Auto merge of #83663 - AngelicosPhosphoros:simplify_binary_and_to_get…
Browse files Browse the repository at this point in the history
…_better_asm, r=nagisa

Simplify logical operations CFG

This is basically same commit as e38e954 which was reverted later in 676953f
In both cases, this changes weren't benchmarked.
e38e954 leads to missed optimization described in [this issue](#62993)
676953f leads to missed optimization described in [this issue](#83623)
  • Loading branch information
bors committed Apr 2, 2021
2 parents d474075 + 4464cc2 commit d1065e6
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 317 deletions.
47 changes: 18 additions & 29 deletions compiler/rustc_mir_build/src/build/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,60 +111,49 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ExprKind::LogicalOp { op, lhs, rhs } => {
// And:
//
// [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block]
// | | (false)
// +----------false-----------+------------------> [false_block]
// [block: If(lhs)] -true-> [else_block: dest = (rhs)]
// | (false)
// [shortcurcuit_block: dest = false]
//
// Or:
//
// [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block]
// | (true) | (false)
// [true_block] [false_block]
// [block: If(lhs)] -false-> [else_block: dest = (rhs)]
// | (true)
// [shortcurcuit_block: dest = true]

let (true_block, false_block, mut else_block, join_block) = (
this.cfg.start_new_block(),
let (shortcircuit_block, mut else_block, join_block) = (
this.cfg.start_new_block(),
this.cfg.start_new_block(),
this.cfg.start_new_block(),
);

let lhs = unpack!(block = this.as_local_operand(block, lhs));
let blocks = match op {
LogicalOp::And => (else_block, false_block),
LogicalOp::Or => (true_block, else_block),
LogicalOp::And => (else_block, shortcircuit_block),
LogicalOp::Or => (shortcircuit_block, else_block),
};
let term = TerminatorKind::if_(this.tcx, lhs, blocks.0, blocks.1);
this.cfg.terminate(block, source_info, term);

let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs));
let term = TerminatorKind::if_(this.tcx, rhs, true_block, false_block);
this.cfg.terminate(else_block, source_info, term);

this.cfg.push_assign_constant(
true_block,
shortcircuit_block,
source_info,
destination,
Constant {
span: expr_span,
user_ty: None,
literal: ty::Const::from_bool(this.tcx, true).into(),
literal: match op {
LogicalOp::And => ty::Const::from_bool(this.tcx, false).into(),
LogicalOp::Or => ty::Const::from_bool(this.tcx, true).into(),
},
},
);
this.cfg.goto(shortcircuit_block, source_info, join_block);

this.cfg.push_assign_constant(
false_block,
source_info,
destination,
Constant {
span: expr_span,
user_ty: None,
literal: ty::Const::from_bool(this.tcx, false).into(),
},
);
let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs));
this.cfg.push_assign(else_block, source_info, destination, Rvalue::Use(rhs));
this.cfg.goto(else_block, source_info, join_block);

// Link up both branches:
this.cfg.goto(true_block, source_info, join_block);
this.cfg.goto(false_block, source_info, join_block);
join_block.unit()
}
ExprKind::Loop { body } => {
Expand Down
46 changes: 46 additions & 0 deletions src/test/codegen/issue-83623-SIMD-PartialEq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// This test checks that jumps generated by logical operators can be optimized away

// compile-flags: -Copt-level=3
// only-64bit

#![crate_type="lib"]

pub struct Blueprint {
pub fuel_tank_size: u32,
pub payload: u32,
pub wheel_diameter: u32,
pub wheel_width: u32,
pub storage: u32,
}

// && chains should not prevent SIMD optimizations for primitives
impl PartialEq for Blueprint{
fn eq(&self, other: &Self)->bool{
// CHECK-NOT: call{{.*}}bcmp
// CHECK-NOT: call{{.*}}memcmp
// CHECK-NOT: br {{.*}}
self.fuel_tank_size == other.fuel_tank_size
&& self.payload == other.payload
&& self.wheel_diameter == other.wheel_diameter
&& self.wheel_width == other.wheel_width
&& self.storage == other.storage
}
}

#[derive(PartialEq)]
pub struct Blueprint2 {
pub fuel_tank_size: u32,
pub payload: u32,
pub wheel_diameter: u32,
pub wheel_width: u32,
pub storage: u32,
}

// Derived PartialEq should not generate jumps and should use SIMD
#[no_mangle]
pub fn partial_eq_should_not_jump(a: &Blueprint2, b:&Blueprint2)->bool{
// CHECK-NOT: call{{.*}}bcmp
// CHECK-NOT: call{{.*}}memcmp
// CHECK-NOT: br {{.*}}
a==b
}
Loading

0 comments on commit d1065e6

Please sign in to comment.