Remove unneeded FunctionCx from some codegen methods · rust-lang/rust@ed06f36 (original) (raw)

`@@ -278,7 +278,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

`

278

278

`{

`

279

279

`let from_backend_ty = bx.backend_type(operand.layout);

`

280

280

`let to_backend_ty = bx.backend_type(cast);

`

281

``

`-

Some(OperandValue::Immediate(self.transmute_immediate(

`

``

281

`+

Some(OperandValue::Immediate(transmute_immediate(

`

282

282

` bx,

`

283

283

` imm,

`

284

284

` from_scalar,

`

`@@ -303,8 +303,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

`

303

303

`let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false);

`

304

304

`let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false);

`

305

305

`Some(OperandValue::Pair(

`

306

``

`-

self.transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty),

`

307

``

`-

self.transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty),

`

``

306

`+

transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty),

`

``

307

`+

transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty),

`

308

308

`))

`

309

309

`} else {

`

310

310

`None

`

`@@ -332,7 +332,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

`

332

332

`` // valid ranges. For example, chars are passed as just i32, with no

``

333

333

`// way for LLVM to know that they're 0x10FFFF at most. Thus we assume

`

334

334

`// the range of the input value too, not just the output range.

`

335

``

`-

self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);

`

``

335

`+

assume_scalar_range(bx, imm, from_scalar, from_backend_ty);

`

336

336

``

337

337

` imm = match (from_scalar.primitive(), to_scalar.primitive()) {

`

338

338

`(Int(_, is_signed), Int(..)) => bx.intcast(imm, to_backend_ty, is_signed),

`

`@@ -365,98 +365,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

`

365

365

`Some(imm)

`

366

366

`}

`

367

367

``

368

``

`` -

/// Transmutes one of the immediates from an [OperandValue::Immediate]

``

369

``

`` -

/// or an [OperandValue::Pair] to an immediate of the target type.

``

370

``

`-

///

`

371

``

`` -

/// to_backend_ty must be the non-immediate backend type (so it will be

``

372

``

`` -

/// i8, not i1, for bool-like types.)

``

373

``

`-

fn transmute_immediate(

`

374

``

`-

&self,

`

375

``

`-

bx: &mut Bx,

`

376

``

`-

mut imm: Bx::Value,

`

377

``

`-

from_scalar: abi::Scalar,

`

378

``

`-

from_backend_ty: Bx::Type,

`

379

``

`-

to_scalar: abi::Scalar,

`

380

``

`-

to_backend_ty: Bx::Type,

`

381

``

`-

) -> Bx::Value {

`

382

``

`-

assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));

`

383

``

-

384

``

`-

// While optimizations will remove no-op transmutes, they might still be

`

385

``

`-

// there in debug or things that aren't no-op in MIR because they change

`

386

``

`-

// the Rust type but not the underlying layout/niche.

`

387

``

`-

if from_scalar == to_scalar && from_backend_ty == to_backend_ty {

`

388

``

`-

return imm;

`

389

``

`-

}

`

390

``

-

391

``

`-

use abi::Primitive::*;

`

392

``

`-

imm = bx.from_immediate(imm);

`

393

``

-

394

``

`-

// If we have a scalar, we must already know its range. Either

`

395

``

`-

//

`

396

``

`` -

// 1) It's a parameter with range parameter metadata,

``

397

``

`` -

// 2) It's something we loaded with !range metadata, or

``

398

``

`` -

// 3) After a transmute we assumed the range (see below).

``

399

``

`-

//

`

400

``

`-

// That said, last time we tried removing this, it didn't actually help

`

401

``

`-

// the rustc-perf results, so might as well keep doing it

`

402

``

`-

// https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182

`

403

``

`-

self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);

`

404

``

-

405

``

`-

imm = match (from_scalar.primitive(), to_scalar.primitive()) {

`

406

``

`-

(Int(..) | Float(), Int(..) | Float()) => bx.bitcast(imm, to_backend_ty),

`

407

``

`-

(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),

`

408

``

`-

(Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),

`

409

``

`-

(Pointer(..), Int(..)) => {

`

410

``

`-

// FIXME: this exposes the provenance, which shouldn't be necessary.

`

411

``

`-

bx.ptrtoint(imm, to_backend_ty)

`

412

``

`-

}

`

413

``

`-

(Float(_), Pointer(..)) => {

`

414

``

`-

let int_imm = bx.bitcast(imm, bx.cx().type_isize());

`

415

``

`-

bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)

`

416

``

`-

}

`

417

``

`-

(Pointer(..), Float(_)) => {

`

418

``

`-

// FIXME: this exposes the provenance, which shouldn't be necessary.

`

419

``

`-

let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());

`

420

``

`-

bx.bitcast(int_imm, to_backend_ty)

`

421

``

`-

}

`

422

``

`-

};

`

423

``

-

424

``

`` -

// This assume remains important for cases like (a conceptual)

``

425

``

`-

// transmute::<u32, NonZeroU32>(x) == 0

`

426

``

`-

// since it's never passed to something with parameter metadata (especially

`

427

``

`-

// after MIR inlining) so the only way to tell the backend about the

`

428

``

`` -

// constraint that the transmute introduced is to assume it.

``

429

``

`-

self.assume_scalar_range(bx, imm, to_scalar, to_backend_ty);

`

430

``

-

431

``

`-

imm = bx.to_immediate_scalar(imm, to_scalar);

`

432

``

`-

imm

`

433

``

`-

}

`

434

``

-

435

``

`-

fn assume_scalar_range(

`

436

``

`-

&self,

`

437

``

`-

bx: &mut Bx,

`

438

``

`-

imm: Bx::Value,

`

439

``

`-

scalar: abi::Scalar,

`

440

``

`-

backend_ty: Bx::Type,

`

441

``

`-

) {

`

442

``

`-

if matches!(self.cx.sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(self.cx) {

`

443

``

`-

return;

`

444

``

`-

}

`

445

``

-

446

``

`-

match scalar.primitive() {

`

447

``

`-

abi::Primitive::Int(..) => {

`

448

``

`-

let range = scalar.valid_range(self.cx);

`

449

``

`-

bx.assume_integer_range(imm, backend_ty, range);

`

450

``

`-

}

`

451

``

`-

abi::Primitive::Pointer(abi::AddressSpace::DATA)

`

452

``

`-

if !scalar.valid_range(self.cx).contains(0) =>

`

453

``

`-

{

`

454

``

`-

bx.assume_nonnull(imm);

`

455

``

`-

}

`

456

``

`-

abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {}

`

457

``

`-

}

`

458

``

`-

}

`

459

``

-

460

368

`pub(crate) fn codegen_rvalue_unsized(

`

461

369

`&mut self,

`

462

370

`bx: &mut Bx,

`

`@@ -1231,3 +1139,93 @@ impl OperandValueKind {

`

1231

1139

`})

`

1232

1140

`}

`

1233

1141

`}

`

``

1142

+

``

1143

`` +

/// Transmutes one of the immediates from an [OperandValue::Immediate]

``

``

1144

`` +

/// or an [OperandValue::Pair] to an immediate of the target type.

``

``

1145

`+

///

`

``

1146

`` +

/// to_backend_ty must be the non-immediate backend type (so it will be

``

``

1147

`` +

/// i8, not i1, for bool-like types.)

``

``

1148

`+

fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(

`

``

1149

`+

bx: &mut Bx,

`

``

1150

`+

mut imm: Bx::Value,

`

``

1151

`+

from_scalar: abi::Scalar,

`

``

1152

`+

from_backend_ty: Bx::Type,

`

``

1153

`+

to_scalar: abi::Scalar,

`

``

1154

`+

to_backend_ty: Bx::Type,

`

``

1155

`+

) -> Bx::Value {

`

``

1156

`+

assert_eq!(from_scalar.size(bx.cx()), to_scalar.size(bx.cx()));

`

``

1157

+

``

1158

`+

// While optimizations will remove no-op transmutes, they might still be

`

``

1159

`+

// there in debug or things that aren't no-op in MIR because they change

`

``

1160

`+

// the Rust type but not the underlying layout/niche.

`

``

1161

`+

if from_scalar == to_scalar && from_backend_ty == to_backend_ty {

`

``

1162

`+

return imm;

`

``

1163

`+

}

`

``

1164

+

``

1165

`+

use abi::Primitive::*;

`

``

1166

`+

imm = bx.from_immediate(imm);

`

``

1167

+

``

1168

`+

// If we have a scalar, we must already know its range. Either

`

``

1169

`+

//

`

``

1170

`` +

// 1) It's a parameter with range parameter metadata,

``

``

1171

`` +

// 2) It's something we loaded with !range metadata, or

``

``

1172

`` +

// 3) After a transmute we assumed the range (see below).

``

``

1173

`+

//

`

``

1174

`+

// That said, last time we tried removing this, it didn't actually help

`

``

1175

`+

// the rustc-perf results, so might as well keep doing it

`

``

1176

`+

// https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182

`

``

1177

`+

assume_scalar_range(bx, imm, from_scalar, from_backend_ty);

`

``

1178

+

``

1179

`+

imm = match (from_scalar.primitive(), to_scalar.primitive()) {

`

``

1180

`+

(Int(..) | Float(), Int(..) | Float()) => bx.bitcast(imm, to_backend_ty),

`

``

1181

`+

(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),

`

``

1182

`+

(Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),

`

``

1183

`+

(Pointer(..), Int(..)) => {

`

``

1184

`+

// FIXME: this exposes the provenance, which shouldn't be necessary.

`

``

1185

`+

bx.ptrtoint(imm, to_backend_ty)

`

``

1186

`+

}

`

``

1187

`+

(Float(_), Pointer(..)) => {

`

``

1188

`+

let int_imm = bx.bitcast(imm, bx.cx().type_isize());

`

``

1189

`+

bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)

`

``

1190

`+

}

`

``

1191

`+

(Pointer(..), Float(_)) => {

`

``

1192

`+

// FIXME: this exposes the provenance, which shouldn't be necessary.

`

``

1193

`+

let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());

`

``

1194

`+

bx.bitcast(int_imm, to_backend_ty)

`

``

1195

`+

}

`

``

1196

`+

};

`

``

1197

+

``

1198

`` +

// This assume remains important for cases like (a conceptual)

``

``

1199

`+

// transmute::<u32, NonZeroU32>(x) == 0

`

``

1200

`+

// since it's never passed to something with parameter metadata (especially

`

``

1201

`+

// after MIR inlining) so the only way to tell the backend about the

`

``

1202

`` +

// constraint that the transmute introduced is to assume it.

``

``

1203

`+

assume_scalar_range(bx, imm, to_scalar, to_backend_ty);

`

``

1204

+

``

1205

`+

imm = bx.to_immediate_scalar(imm, to_scalar);

`

``

1206

`+

imm

`

``

1207

`+

}

`

``

1208

+

``

1209

`+

fn assume_scalar_range<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(

`

``

1210

`+

bx: &mut Bx,

`

``

1211

`+

imm: Bx::Value,

`

``

1212

`+

scalar: abi::Scalar,

`

``

1213

`+

backend_ty: Bx::Type,

`

``

1214

`+

) {

`

``

1215

`+

if matches!(bx.cx().sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(bx.cx()) {

`

``

1216

`+

return;

`

``

1217

`+

}

`

``

1218

+

``

1219

`+

match scalar.primitive() {

`

``

1220

`+

abi::Primitive::Int(..) => {

`

``

1221

`+

let range = scalar.valid_range(bx.cx());

`

``

1222

`+

bx.assume_integer_range(imm, backend_ty, range);

`

``

1223

`+

}

`

``

1224

`+

abi::Primitive::Pointer(abi::AddressSpace::DATA)

`

``

1225

`+

if !scalar.valid_range(bx.cx()).contains(0) =>

`

``

1226

`+

{

`

``

1227

`+

bx.assume_nonnull(imm);

`

``

1228

`+

}

`

``

1229

`+

abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {}

`

``

1230

`+

}

`

``

1231

`+

}

`