Widen i128 constant storage
Authored by
mfwolffe <wolffemf@dukes.jmu.edu>
- SHA
5d8242714d082a0219814e29a67ddb23a8971dad- Parents
-
c205da3 - Tree
21f9750
5d82427
5d8242714d082a0219814e29a67ddb23a8971dadc205da3
21f9750| Status | File | + | - |
|---|---|---|---|
| M |
src/codegen/isel.rs
|
3 | 2 |
| M |
src/ir/builder.rs
|
7 | 3 |
| M |
src/ir/inst.rs
|
3 | 3 |
| M |
src/ir/lower.rs
|
27 | 22 |
| M |
src/opt/bce.rs
|
1 | 1 |
| M |
src/opt/const_arg.rs
|
1 | 1 |
| M |
src/opt/const_fold.rs
|
41 | 32 |
| M |
src/opt/const_prop.rs
|
3 | 2 |
| M |
src/opt/cse.rs
|
15 | 15 |
| M |
src/opt/dep_analysis.rs
|
2 | 2 |
| M |
src/opt/gvn.rs
|
14 | 14 |
| M |
src/opt/loop_utils.rs
|
1 | 1 |
| M |
src/opt/peel.rs
|
1 | 1 |
| M |
src/opt/return_prop.rs
|
1 | 1 |
| M |
src/opt/strength_reduce.rs
|
4 | 2 |
| M |
src/opt/unroll.rs
|
4 | 4 |
| M |
src/opt/vectorize.rs
|
1 | 1 |
| A |
tests/fixtures/integer16_wide_values.f90
|
12 | 0 |
| M |
tests/i128_ir.rs
|
28 | 0 |
src/codegen/isel.rsmodified@@ -896,7 +896,7 @@ fn select_inst(mf: &mut MachineFunction, ctx: &mut ISelCtx, mb: MBlockId, inst: | ||
| 896 | 896 | if let Some(idx) = indices.first() { |
| 897 | 897 | let idx_vreg = ctx.lookup_vreg(*idx); |
| 898 | 898 | let tmp = mf.new_vreg(RegClass::Gp64); |
| 899 | - emit_const_int(mf, mb, tmp, elem_size, IntWidth::I64); | |
| 899 | + emit_const_int(mf, mb, tmp, elem_size as i128, IntWidth::I64); | |
| 900 | 900 | let scaled = mf.new_vreg(RegClass::Gp64); |
| 901 | 901 | mf.block_mut(mb).insts.push(MachineInst { |
| 902 | 902 | opcode: ArmOpcode::Mul, |
@@ -1417,7 +1417,8 @@ fn emit_epilogue(mf: &mut MachineFunction, mb: MBlockId) { | ||
| 1417 | 1417 | |
| 1418 | 1418 | /// Emit a constant integer using movz/movk sequence. |
| 1419 | 1419 | /// Respects width: 32-bit values mask to 32 bits and only emit shifts 0/16. |
| 1420 | -fn emit_const_int(mf: &mut MachineFunction, mb: MBlockId, dest: VRegId, val: i64, width: IntWidth) { | |
| 1420 | +fn emit_const_int(mf: &mut MachineFunction, mb: MBlockId, dest: VRegId, val: i128, width: IntWidth) { | |
| 1421 | + debug_assert!(width != IntWidth::I128, "backend should reject i128 before isel"); | |
| 1421 | 1422 | let is_32 = matches!(width, IntWidth::I8 | IntWidth::I16 | IntWidth::I32); |
| 1422 | 1423 | // Mask to the appropriate width to prevent sign-extension artifacts. |
| 1423 | 1424 | let uval = if is_32 { (val as u32) as u64 } else { val as u64 }; |
src/ir/builder.rsmodified@@ -65,16 +65,20 @@ impl<'a> FuncBuilder<'a> { | ||
| 65 | 65 | |
| 66 | 66 | // ---- Constants ---- |
| 67 | 67 | |
| 68 | - pub fn const_int(&mut self, value: i64, width: IntWidth) -> ValueId { | |
| 68 | + pub fn const_int(&mut self, value: i128, width: IntWidth) -> ValueId { | |
| 69 | 69 | self.emit(InstKind::ConstInt(value, width), IrType::Int(width)) |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | 72 | pub fn const_i32(&mut self, value: i32) -> ValueId { |
| 73 | - self.const_int(value as i64, IntWidth::I32) | |
| 73 | + self.const_int(value as i128, IntWidth::I32) | |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | 76 | pub fn const_i64(&mut self, value: i64) -> ValueId { |
| 77 | - self.const_int(value, IntWidth::I64) | |
| 77 | + self.const_int(value as i128, IntWidth::I64) | |
| 78 | + } | |
| 79 | + | |
| 80 | + pub fn const_i128(&mut self, value: i128) -> ValueId { | |
| 81 | + self.const_int(value, IntWidth::I128) | |
| 78 | 82 | } |
| 79 | 83 | |
| 80 | 84 | pub fn const_float(&mut self, value: f64, width: FloatWidth) -> ValueId { |
src/ir/inst.rsmodified@@ -69,7 +69,7 @@ pub struct Inst { | ||
| 69 | 69 | #[derive(Debug, Clone)] |
| 70 | 70 | pub enum InstKind { |
| 71 | 71 | // ---- Constants ---- |
| 72 | - ConstInt(i64, IntWidth), | |
| 72 | + ConstInt(i128, IntWidth), | |
| 73 | 73 | ConstFloat(f64, FloatWidth), |
| 74 | 74 | ConstBool(bool), |
| 75 | 75 | ConstString(Vec<u8>), |
@@ -337,7 +337,7 @@ pub struct Global { | ||
| 337 | 337 | #[derive(Debug, Clone)] |
| 338 | 338 | pub enum GlobalInit { |
| 339 | 339 | Zero, |
| 340 | - Int(i64), | |
| 340 | + Int(i128), | |
| 341 | 341 | Float(f64), |
| 342 | 342 | String(Vec<u8>), |
| 343 | 343 | /// Array literal: a sequence of per-element initializers of |
@@ -346,7 +346,7 @@ pub enum GlobalInit { | ||
| 346 | 346 | /// constructors. The Vec's length is the array's total element |
| 347 | 347 | /// count (product of dims); shorter initializers are padded |
| 348 | 348 | /// with Zero at lowering time. |
| 349 | - IntArray(Vec<i64>), | |
| 349 | + IntArray(Vec<i128>), | |
| 350 | 350 | FloatArray(Vec<f64>), |
| 351 | 351 | } |
| 352 | 352 | |
src/ir/lower.rsmodified@@ -736,7 +736,7 @@ fn collect_module_globals( | ||
| 736 | 736 | /// 2. `[(expr, i = lo, hi[, step])]` implied-do iterator |
| 737 | 737 | /// 3. `reshape(constructor, shape)` reshape of (1) or (2) |
| 738 | 738 | /// |
| 739 | -/// Each path produces a flat list of `i64` (for integer types) | |
| 739 | +/// Each path produces a flat list of `i128` (for integer types) | |
| 740 | 740 | /// or `f64` (for float types) of length `total`. Shorter lists |
| 741 | 741 | /// are zero-padded; longer lists return `None` (a future Maj-3 |
| 742 | 742 | /// fix will add a proper diagnostic for shape-mismatch errors). |
@@ -762,9 +762,9 @@ fn eval_const_array_init( | ||
| 762 | 762 | while (out.len() as i64) < total { out.push(0.0); } |
| 763 | 763 | Some(GlobalInit::FloatArray(out)) |
| 764 | 764 | } else { |
| 765 | - let mut out: Vec<i64> = scalars.iter().map(|s| match s { | |
| 765 | + let mut out: Vec<i128> = scalars.iter().map(|s| match s { | |
| 766 | 766 | ConstScalar::Int(i) => *i, |
| 767 | - ConstScalar::Float(f) => *f as i64, | |
| 767 | + ConstScalar::Float(f) => *f as i128, | |
| 768 | 768 | }).collect(); |
| 769 | 769 | while (out.len() as i64) < total { out.push(0); } |
| 770 | 770 | Some(GlobalInit::IntArray(out)) |
@@ -1239,15 +1239,15 @@ fn lower_unit( | ||
| 1239 | 1239 | /// global address + load. |
| 1240 | 1240 | fn materialize_const_scalar(b: &mut FuncBuilder, c: ConstScalar, target: &IrType) -> ValueId { |
| 1241 | 1241 | match (c, target) { |
| 1242 | - (ConstScalar::Int(i), IrType::Int(IntWidth::I128)) => b.const_int(i, IntWidth::I128), | |
| 1243 | - (ConstScalar::Int(i), IrType::Int(IntWidth::I64)) => b.const_i64(i), | |
| 1242 | + (ConstScalar::Int(i), IrType::Int(IntWidth::I128)) => b.const_i128(i), | |
| 1243 | + (ConstScalar::Int(i), IrType::Int(IntWidth::I64)) => b.const_i64(i as i64), | |
| 1244 | 1244 | (ConstScalar::Int(i), IrType::Int(_)) => b.const_i32(i as i32), |
| 1245 | 1245 | (ConstScalar::Int(i), IrType::Bool) => b.const_bool(i != 0), |
| 1246 | 1246 | (ConstScalar::Int(i), IrType::Float(FloatWidth::F64)) => b.const_f64(i as f64), |
| 1247 | 1247 | (ConstScalar::Int(i), IrType::Float(FloatWidth::F32)) => b.const_f32(i as f32), |
| 1248 | 1248 | (ConstScalar::Float(f), IrType::Float(FloatWidth::F64)) => b.const_f64(f), |
| 1249 | 1249 | (ConstScalar::Float(f), IrType::Float(FloatWidth::F32)) => b.const_f32(f as f32), |
| 1250 | - (ConstScalar::Float(f), IrType::Int(IntWidth::I128)) => b.const_int(f as i64, IntWidth::I128), | |
| 1250 | + (ConstScalar::Float(f), IrType::Int(IntWidth::I128)) => b.const_i128(f as i128), | |
| 1251 | 1251 | (ConstScalar::Float(f), IrType::Int(IntWidth::I64)) => b.const_i64(f as i64), |
| 1252 | 1252 | (ConstScalar::Float(f), IrType::Int(_)) => b.const_i32(f as i32), |
| 1253 | 1253 | // Fallback — emit a zero of the target's class. |
@@ -1264,13 +1264,16 @@ fn materialize_const_scalar(b: &mut FuncBuilder, c: ConstScalar, target: &IrType | ||
| 1264 | 1264 | fn clamp_const_to_type(v: ConstScalar, target: &IrType) -> ConstScalar { |
| 1265 | 1265 | match (v, target) { |
| 1266 | 1266 | (ConstScalar::Int(i), IrType::Int(IntWidth::I8)) => { |
| 1267 | - ConstScalar::Int((i as i8) as i64) | |
| 1267 | + ConstScalar::Int((i as i8) as i128) | |
| 1268 | 1268 | } |
| 1269 | 1269 | (ConstScalar::Int(i), IrType::Int(IntWidth::I16)) => { |
| 1270 | - ConstScalar::Int((i as i16) as i64) | |
| 1270 | + ConstScalar::Int((i as i16) as i128) | |
| 1271 | 1271 | } |
| 1272 | 1272 | (ConstScalar::Int(i), IrType::Int(IntWidth::I32)) => { |
| 1273 | - ConstScalar::Int((i as i32) as i64) | |
| 1273 | + ConstScalar::Int((i as i32) as i128) | |
| 1274 | + } | |
| 1275 | + (ConstScalar::Int(i), IrType::Int(IntWidth::I64)) => { | |
| 1276 | + ConstScalar::Int((i as i64) as i128) | |
| 1274 | 1277 | } |
| 1275 | 1278 | (ConstScalar::Int(i), IrType::Bool) => { |
| 1276 | 1279 | ConstScalar::Int(if i != 0 { 1 } else { 0 }) |
@@ -1317,7 +1320,7 @@ fn eval_const_global_init( | ||
| 1317 | 1320 | /// used for real/double precision. |
| 1318 | 1321 | #[derive(Debug, Clone, Copy)] |
| 1319 | 1322 | enum ConstScalar { |
| 1320 | - Int(i64), | |
| 1323 | + Int(i128), | |
| 1321 | 1324 | Float(f64), |
| 1322 | 1325 | } |
| 1323 | 1326 | |
@@ -1333,7 +1336,7 @@ fn eval_const_scalar( | ||
| 1333 | 1336 | ) -> Option<ConstScalar> { |
| 1334 | 1337 | use crate::ast::expr::{UnaryOp, BinaryOp}; |
| 1335 | 1338 | match &e.node { |
| 1336 | - Expr::IntegerLiteral { text, .. } => text.parse::<i64>().ok().map(ConstScalar::Int), | |
| 1339 | + Expr::IntegerLiteral { text, .. } => text.parse::<i128>().ok().map(ConstScalar::Int), | |
| 1337 | 1340 | Expr::RealLiteral { text, .. } => { |
| 1338 | 1341 | text.replace('d', "e").replace('D', "E").parse::<f64>().ok().map(ConstScalar::Float) |
| 1339 | 1342 | } |
@@ -1393,8 +1396,8 @@ fn eval_const_scalar( | ||
| 1393 | 1396 | } |
| 1394 | 1397 | BinaryOp::Pow => { |
| 1395 | 1398 | // Integer power with non-negative exponent. |
| 1396 | - if r < 0 || r > i32::MAX as i64 { return None; } | |
| 1397 | - let mut acc: i64 = 1; | |
| 1399 | + if r < 0 || r > i32::MAX as i128 { return None; } | |
| 1400 | + let mut acc: i128 = 1; | |
| 1398 | 1401 | for _ in 0..r { acc = acc.wrapping_mul(l); } |
| 1399 | 1402 | Some(ConstScalar::Int(acc)) |
| 1400 | 1403 | } |
@@ -1921,7 +1924,7 @@ fn install_globals_as_locals( | ||
| 1921 | 1924 | by_ref: false, |
| 1922 | 1925 | char_kind: CharKind::None, |
| 1923 | 1926 | derived_type: None, |
| 1924 | - inline_const: Some(ConstScalar::Int(cv)), | |
| 1927 | + inline_const: Some(ConstScalar::Int(cv as i128)), | |
| 1925 | 1928 | }); |
| 1926 | 1929 | installed_from.insert(local_key, mod_key); |
| 1927 | 1930 | } |
@@ -7439,17 +7442,19 @@ fn lower_expr_full( | ||
| 7439 | 7442 | ) -> ValueId { |
| 7440 | 7443 | match &expr.node { |
| 7441 | 7444 | Expr::IntegerLiteral { text, kind, .. } => { |
| 7442 | - let val: i64 = text.parse().unwrap_or(0); | |
| 7443 | 7445 | let kind = kind.as_deref(); |
| 7444 | 7446 | if kind == Some("16") { |
| 7445 | - b.const_int(val, IntWidth::I128) | |
| 7446 | - } else if kind == Some("8") | |
| 7447 | - || val > i32::MAX as i64 | |
| 7448 | - || val < i32::MIN as i64 | |
| 7449 | - { | |
| 7450 | - b.const_i64(val) | |
| 7447 | + b.const_i128(text.parse::<i128>().unwrap_or(0)) | |
| 7451 | 7448 | } else { |
| 7452 | - b.const_i32(val as i32) | |
| 7449 | + let val: i64 = text.parse().unwrap_or(0); | |
| 7450 | + if kind == Some("8") | |
| 7451 | + || val > i32::MAX as i64 | |
| 7452 | + || val < i32::MIN as i64 | |
| 7453 | + { | |
| 7454 | + b.const_i64(val) | |
| 7455 | + } else { | |
| 7456 | + b.const_i32(val as i32) | |
| 7457 | + } | |
| 7453 | 7458 | } |
| 7454 | 7459 | } |
| 7455 | 7460 | Expr::RealLiteral { text, .. } => { |
src/opt/bce.rsmodified@@ -249,7 +249,7 @@ fn update_step_const(func: &Function, index: ValueId, next: ValueId) -> Option<i | ||
| 249 | 249 | fn resolve_int_scalar(func: &Function, value: ValueId) -> Option<i64> { |
| 250 | 250 | let kind = find_inst_kind(func, value)?; |
| 251 | 251 | match kind { |
| 252 | - InstKind::ConstInt(v, _) => Some(*v), | |
| 252 | + InstKind::ConstInt(v, _) => i64::try_from(*v).ok(), | |
| 253 | 253 | InstKind::IntExtend(src, _, _) | InstKind::IntTrunc(src, _) => { |
| 254 | 254 | resolve_int_scalar(func, *src) |
| 255 | 255 | } |
src/opt/const_arg.rsmodified@@ -46,7 +46,7 @@ enum ParamMode { | ||
| 46 | 46 | |
| 47 | 47 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 48 | 48 | enum ScalarConst { |
| 49 | - Int(i64, IntWidth), | |
| 49 | + Int(i128, IntWidth), | |
| 50 | 50 | Float(u64, FloatWidth), |
| 51 | 51 | Bool(bool), |
| 52 | 52 | } |
src/opt/const_fold.rsmodified@@ -33,7 +33,7 @@ use std::collections::HashMap; | ||
| 33 | 33 | /// Compile-time constant value, normalized for folding. |
| 34 | 34 | #[derive(Debug, Clone, Copy)] |
| 35 | 35 | enum Const { |
| 36 | - Int(i64, IntWidth), | |
| 36 | + Int(i128, IntWidth), | |
| 37 | 37 | Float(f64, FloatWidth), |
| 38 | 38 | Bool(bool), |
| 39 | 39 | } |
@@ -68,29 +68,39 @@ impl Const { | ||
| 68 | 68 | } |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | -/// Sign-extend `v` from `bits` to a full i64. Used so that comparisons | |
| 71 | +/// Sign-extend `v` from `bits` to a full i128. Used so that comparisons | |
| 72 | 72 | /// and arithmetic on narrower integer types match hardware behavior. |
| 73 | -fn sext(v: i64, bits: u32) -> i64 { | |
| 74 | - if bits >= 64 { v } | |
| 73 | +fn sext(v: i128, bits: u32) -> i128 { | |
| 74 | + if bits >= 128 { v } | |
| 75 | 75 | else { |
| 76 | - let shift = 64 - bits; | |
| 76 | + let shift = 128 - bits; | |
| 77 | 77 | (v << shift) >> shift |
| 78 | 78 | } |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | -/// Mask `v` down to `bits` low bits. The IR stores integers as i64 but | |
| 81 | +/// Mask `v` down to `bits` low bits. The IR stores integers as i128 but | |
| 82 | 82 | /// arithmetic must wrap at the declared width. |
| 83 | -fn mask(v: i64, bits: u32) -> i64 { | |
| 84 | - if bits >= 64 { v } | |
| 85 | - else { v & ((1i64 << bits) - 1) } | |
| 83 | +fn mask(v: i128, bits: u32) -> i128 { | |
| 84 | + if bits >= 128 { v } | |
| 85 | + else { v & ((1i128 << bits) - 1) } | |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | /// Truncate-then-sign-extend a wide arithmetic result back to its |
| 89 | -/// declared width, normalized to a sign-extended i64. | |
| 90 | -fn norm(v: i64, w: IntWidth) -> i64 { | |
| 89 | +/// declared width, normalized to a sign-extended i128. | |
| 90 | +fn norm(v: i128, w: IntWidth) -> i128 { | |
| 91 | 91 | sext(mask(v, w.bits()), w.bits()) |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | +fn signed_min(w: IntWidth) -> i128 { | |
| 95 | + match w { | |
| 96 | + IntWidth::I8 => i8::MIN as i128, | |
| 97 | + IntWidth::I16 => i16::MIN as i128, | |
| 98 | + IntWidth::I32 => i32::MIN as i128, | |
| 99 | + IntWidth::I64 => i64::MIN as i128, | |
| 100 | + IntWidth::I128 => i128::MIN, | |
| 101 | + } | |
| 102 | +} | |
| 103 | + | |
| 94 | 104 | /// Round an `f64`-stored value to the precision of its declared |
| 95 | 105 | /// `FloatWidth`. Audit B-3: used as defense in depth in `FCmp` and |
| 96 | 106 | /// `FloatToInt` so that those folds don't silently miscompute when |
@@ -138,10 +148,9 @@ fn try_fold(kind: &InstKind, ty: &IrType, consts: &HashMap<ValueId, Const>) -> O | ||
| 138 | 148 | } |
| 139 | 149 | InstKind::IDiv(a, b) => { |
| 140 | 150 | if let (Some(Const::Int(av, _)), Some(Const::Int(bv, _))) = (get(a), get(b)) { |
| 141 | - if bv == 0 { return None; } // leave divide-by-zero to runtime | |
| 142 | - // i64::MIN / -1 also overflows; bail to keep behavior identical. | |
| 143 | - if av == i64::MIN && bv == -1 { return None; } | |
| 144 | 151 | if let IrType::Int(w) = ty { |
| 152 | + if bv == 0 { return None; } // leave divide-by-zero to runtime | |
| 153 | + if av == signed_min(*w) && bv == -1 { return None; } | |
| 145 | 154 | return Some(InstKind::ConstInt(norm(av / bv, *w), *w)); |
| 146 | 155 | } |
| 147 | 156 | } |
@@ -149,9 +158,9 @@ fn try_fold(kind: &InstKind, ty: &IrType, consts: &HashMap<ValueId, Const>) -> O | ||
| 149 | 158 | } |
| 150 | 159 | InstKind::IMod(a, b) => { |
| 151 | 160 | if let (Some(Const::Int(av, _)), Some(Const::Int(bv, _))) = (get(a), get(b)) { |
| 152 | - if bv == 0 { return None; } | |
| 153 | - if av == i64::MIN && bv == -1 { return None; } | |
| 154 | 161 | if let IrType::Int(w) = ty { |
| 162 | + if bv == 0 { return None; } | |
| 163 | + if av == signed_min(*w) && bv == -1 { return None; } | |
| 155 | 164 | return Some(InstKind::ConstInt(norm(av % bv, *w), *w)); |
| 156 | 165 | } |
| 157 | 166 | } |
@@ -267,7 +276,7 @@ fn try_fold(kind: &InstKind, ty: &IrType, consts: &HashMap<ValueId, Const>) -> O | ||
| 267 | 276 | InstKind::Shl(a, b) => { |
| 268 | 277 | if let (Some(Const::Int(av, _)), Some(Const::Int(bv, _))) = (get(a), get(b)) { |
| 269 | 278 | if let IrType::Int(w) = ty { |
| 270 | - let bits = w.bits() as i64; | |
| 279 | + let bits = w.bits() as i128; | |
| 271 | 280 | if (0..bits).contains(&bv) { |
| 272 | 281 | return Some(InstKind::ConstInt( |
| 273 | 282 | norm(av.wrapping_shl(bv as u32), *w), |
@@ -282,10 +291,10 @@ fn try_fold(kind: &InstKind, ty: &IrType, consts: &HashMap<ValueId, Const>) -> O | ||
| 282 | 291 | InstKind::LShr(a, b) => { |
| 283 | 292 | if let (Some(Const::Int(av, _)), Some(Const::Int(bv, _))) = (get(a), get(b)) { |
| 284 | 293 | if let IrType::Int(w) = ty { |
| 285 | - let bits = w.bits() as i64; | |
| 294 | + let bits = w.bits() as i128; | |
| 286 | 295 | if (0..bits).contains(&bv) { |
| 287 | - let unsigned = (mask(av, w.bits()) as u64) >> (bv as u32); | |
| 288 | - return Some(InstKind::ConstInt(norm(unsigned as i64, *w), *w)); | |
| 296 | + let unsigned = (mask(av, w.bits()) as u128) >> (bv as u32); | |
| 297 | + return Some(InstKind::ConstInt(norm(unsigned as i128, *w), *w)); | |
| 289 | 298 | } |
| 290 | 299 | return None; |
| 291 | 300 | } |
@@ -295,7 +304,7 @@ fn try_fold(kind: &InstKind, ty: &IrType, consts: &HashMap<ValueId, Const>) -> O | ||
| 295 | 304 | InstKind::AShr(a, b) => { |
| 296 | 305 | if let (Some(Const::Int(av, _)), Some(Const::Int(bv, _))) = (get(a), get(b)) { |
| 297 | 306 | if let IrType::Int(w) = ty { |
| 298 | - let bits = w.bits() as i64; | |
| 307 | + let bits = w.bits() as i128; | |
| 299 | 308 | if (0..bits).contains(&bv) { |
| 300 | 309 | let signed = sext(av, w.bits()) >> (bv as u32); |
| 301 | 310 | return Some(InstKind::ConstInt(norm(signed, *w), *w)); |
@@ -314,19 +323,19 @@ fn try_fold(kind: &InstKind, ty: &IrType, consts: &HashMap<ValueId, Const>) -> O | ||
| 314 | 323 | // produce a wrong-width constant if we kept reading from `w`. |
| 315 | 324 | InstKind::PopCount(a) => { |
| 316 | 325 | if let (Some(Const::Int(av, src_w)), IrType::Int(out_w)) = (get(a), ty) { |
| 317 | - let val = mask(av, src_w.bits()) as u64; | |
| 318 | - return Some(InstKind::ConstInt(norm(val.count_ones() as i64, *out_w), *out_w)); | |
| 326 | + let val = mask(av, src_w.bits()) as u128; | |
| 327 | + return Some(InstKind::ConstInt(norm(val.count_ones() as i128, *out_w), *out_w)); | |
| 319 | 328 | } |
| 320 | 329 | None |
| 321 | 330 | } |
| 322 | 331 | InstKind::CountLeadingZeros(a) => { |
| 323 | 332 | if let (Some(Const::Int(av, src_w)), IrType::Int(out_w)) = (get(a), ty) { |
| 324 | 333 | let bits = src_w.bits(); |
| 325 | - let val = mask(av, bits) as u64; | |
| 334 | + let val = mask(av, bits) as u128; | |
| 326 | 335 | let lz = if val == 0 { |
| 327 | - bits as i64 | |
| 336 | + bits as i128 | |
| 328 | 337 | } else { |
| 329 | - (val.leading_zeros() as i64) - (64 - bits as i64) | |
| 338 | + (val.leading_zeros() as i128) - (128 - bits as i128) | |
| 330 | 339 | }; |
| 331 | 340 | return Some(InstKind::ConstInt(norm(lz, *out_w), *out_w)); |
| 332 | 341 | } |
@@ -335,8 +344,8 @@ fn try_fold(kind: &InstKind, ty: &IrType, consts: &HashMap<ValueId, Const>) -> O | ||
| 335 | 344 | InstKind::CountTrailingZeros(a) => { |
| 336 | 345 | if let (Some(Const::Int(av, src_w)), IrType::Int(out_w)) = (get(a), ty) { |
| 337 | 346 | let bits = src_w.bits(); |
| 338 | - let val = mask(av, bits) as u64; | |
| 339 | - let tz = if val == 0 { bits as i64 } else { val.trailing_zeros() as i64 }; | |
| 347 | + let val = mask(av, bits) as u128; | |
| 348 | + let tz = if val == 0 { bits as i128 } else { val.trailing_zeros() as i128 }; | |
| 340 | 349 | return Some(InstKind::ConstInt(norm(tz, *out_w), *out_w)); |
| 341 | 350 | } |
| 342 | 351 | None |
@@ -383,17 +392,17 @@ fn try_fold(kind: &InstKind, ty: &IrType, consts: &HashMap<ValueId, Const>) -> O | ||
| 383 | 392 | IntWidth::I16 => i16::MIN as f64, |
| 384 | 393 | IntWidth::I32 => i32::MIN as f64, |
| 385 | 394 | IntWidth::I64 => i64::MIN as f64, |
| 386 | - IntWidth::I128 => i64::MIN as f64, | |
| 395 | + IntWidth::I128 => return None, | |
| 387 | 396 | }; |
| 388 | 397 | let hi = match w { |
| 389 | 398 | IntWidth::I8 => i8::MAX as f64, |
| 390 | 399 | IntWidth::I16 => i16::MAX as f64, |
| 391 | 400 | IntWidth::I32 => i32::MAX as f64, |
| 392 | 401 | IntWidth::I64 => i64::MAX as f64, |
| 393 | - IntWidth::I128 => i64::MAX as f64, | |
| 402 | + IntWidth::I128 => return None, | |
| 394 | 403 | }; |
| 395 | 404 | if truncd < lo || truncd > hi { return None; } |
| 396 | - return Some(InstKind::ConstInt(norm(truncd as i64, *w), *w)); | |
| 405 | + return Some(InstKind::ConstInt(norm(truncd as i128, *w), *w)); | |
| 397 | 406 | } |
| 398 | 407 | None |
| 399 | 408 | } |
@@ -513,7 +522,7 @@ where F: FnOnce(f64) -> f64 | ||
| 513 | 522 | } |
| 514 | 523 | |
| 515 | 524 | fn fold_int_bin<F>(a: Option<Const>, b: Option<Const>, ty: &IrType, op: F) -> Option<InstKind> |
| 516 | -where F: FnOnce(i64, i64) -> i64 | |
| 525 | +where F: FnOnce(i128, i128) -> i128 | |
| 517 | 526 | { |
| 518 | 527 | if let (Some(Const::Int(av, _)), Some(Const::Int(bv, _))) = (a, b) { |
| 519 | 528 | if let IrType::Int(w) = ty { |
src/opt/const_prop.rsmodified@@ -56,10 +56,11 @@ impl Const { | ||
| 56 | 56 | InstKind::ConstInt(v, w) => { |
| 57 | 57 | let bits = w.bits(); |
| 58 | 58 | let signed = if bits >= 64 { |
| 59 | - *v | |
| 59 | + i64::try_from(*v).ok()? | |
| 60 | 60 | } else { |
| 61 | 61 | let shift = 64 - bits; |
| 62 | - (*v << shift) >> shift | |
| 62 | + let narrow = i64::try_from(*v).ok()?; | |
| 63 | + (narrow << shift) >> shift | |
| 63 | 64 | }; |
| 64 | 65 | Some(Const::Int(signed, *w)) |
| 65 | 66 | } |
src/opt/cse.rsmodified@@ -47,7 +47,7 @@ struct Key { | ||
| 47 | 47 | tag: u32, |
| 48 | 48 | operands: Vec<ValueId>, |
| 49 | 49 | /// Auxiliary integer (used for things like comparison op, bitwidth, etc.) |
| 50 | - aux: i64, | |
| 50 | + aux: i128, | |
| 51 | 51 | /// Optional name for instructions whose value depends on a |
| 52 | 52 | /// symbol (currently only `GlobalAddr`). Audit Med-2: a hashed |
| 53 | 53 | /// aux risked theoretical SipHash13 collisions merging two |
@@ -62,7 +62,7 @@ struct Key { | ||
| 62 | 62 | /// Build a canonical key for an instruction. Returns `None` if the |
| 63 | 63 | /// instruction is impure or otherwise not a CSE candidate. |
| 64 | 64 | fn key_of(inst: &Inst) -> Option<Key> { |
| 65 | - let mk = |tag: u32, ops: Vec<ValueId>, aux: i64| -> Option<Key> { | |
| 65 | + let mk = |tag: u32, ops: Vec<ValueId>, aux: i128| -> Option<Key> { | |
| 66 | 66 | Some(Key { tag, operands: ops, aux, name: None, ty: inst.ty.clone() }) |
| 67 | 67 | }; |
| 68 | 68 | let mk_named = |tag: u32, name: String| -> Option<Key> { |
@@ -90,15 +90,15 @@ fn key_of(inst: &Inst) -> Option<Key> { | ||
| 90 | 90 | InstKind::ConstInt(v, w) => { |
| 91 | 91 | let bits = w.bits(); |
| 92 | 92 | // Sign-extend at width: low `bits` bits → i64 sign-extended. |
| 93 | - let signed = if bits >= 64 { | |
| 93 | + let signed = if bits >= 128 { | |
| 94 | 94 | *v |
| 95 | 95 | } else { |
| 96 | - let shift = 64 - bits; | |
| 96 | + let shift = 128 - bits; | |
| 97 | 97 | (*v << shift) >> shift |
| 98 | 98 | }; |
| 99 | 99 | mk(1, vec![], signed) |
| 100 | 100 | } |
| 101 | - InstKind::ConstFloat(v, _) => mk(2, vec![], v.to_bits() as i64), | |
| 101 | + InstKind::ConstFloat(v, _) => mk(2, vec![], v.to_bits() as i128), | |
| 102 | 102 | InstKind::ConstBool(b) => mk(3, vec![], if *b { 1 } else { 0 }), |
| 103 | 103 | |
| 104 | 104 | // Integer arithmetic -------------------------------------------- |
@@ -121,12 +121,12 @@ fn key_of(inst: &Inst) -> Option<Key> { | ||
| 121 | 121 | |
| 122 | 122 | // Comparisons --------------------------------------------------- |
| 123 | 123 | InstKind::ICmp(op, a, b) => { |
| 124 | - let aux = *op as i64; | |
| 124 | + let aux = *op as i128; | |
| 125 | 125 | let ops = match op { CmpOp::Eq | CmpOp::Ne => canon(*a, *b), _ => vec![*a, *b] }; |
| 126 | 126 | mk(30, ops, aux) |
| 127 | 127 | } |
| 128 | 128 | InstKind::FCmp(op, a, b) => { |
| 129 | - let aux = *op as i64; | |
| 129 | + let aux = *op as i128; | |
| 130 | 130 | let ops = match op { CmpOp::Eq | CmpOp::Ne => canon(*a, *b), _ => vec![*a, *b] }; |
| 131 | 131 | mk(31, ops, aux) |
| 132 | 132 | } |
@@ -151,12 +151,12 @@ fn key_of(inst: &Inst) -> Option<Key> { | ||
| 151 | 151 | InstKind::PopCount(a) => mk(59, vec![*a], 0), |
| 152 | 152 | |
| 153 | 153 | // Conversions --------------------------------------------------- |
| 154 | - InstKind::IntToFloat(v, fw) => mk(60, vec![*v], fw.bits() as i64), | |
| 155 | - InstKind::FloatToInt(v, w) => mk(61, vec![*v], w.bits() as i64), | |
| 156 | - InstKind::FloatExtend(v, fw) => mk(62, vec![*v], fw.bits() as i64), | |
| 157 | - InstKind::FloatTrunc(v, fw) => mk(63, vec![*v], fw.bits() as i64), | |
| 158 | - InstKind::IntExtend(v, w, sgn) => mk(64, vec![*v], (w.bits() as i64) | ((*sgn as i64) << 32)), | |
| 159 | - InstKind::IntTrunc(v, w) => mk(65, vec![*v], w.bits() as i64), | |
| 154 | + InstKind::IntToFloat(v, fw) => mk(60, vec![*v], fw.bits() as i128), | |
| 155 | + InstKind::FloatToInt(v, w) => mk(61, vec![*v], w.bits() as i128), | |
| 156 | + InstKind::FloatExtend(v, fw) => mk(62, vec![*v], fw.bits() as i128), | |
| 157 | + InstKind::FloatTrunc(v, fw) => mk(63, vec![*v], fw.bits() as i128), | |
| 158 | + InstKind::IntExtend(v, w, sgn) => mk(64, vec![*v], (w.bits() as i128) | ((*sgn as i128) << 32)), | |
| 159 | + InstKind::IntTrunc(v, w) => mk(65, vec![*v], w.bits() as i128), | |
| 160 | 160 | |
| 161 | 161 | // Address arithmetic -------------------------------------------- |
| 162 | 162 | InstKind::GetElementPtr(base, idxs) => { |
@@ -166,10 +166,10 @@ fn key_of(inst: &Inst) -> Option<Key> { | ||
| 166 | 166 | } |
| 167 | 167 | |
| 168 | 168 | // Aggregates ---------------------------------------------------- |
| 169 | - InstKind::ExtractField(agg, i) => mk(80, vec![*agg], *i as i64), | |
| 169 | + InstKind::ExtractField(agg, i) => mk(80, vec![*agg], *i as i128), | |
| 170 | 170 | // InsertField produces a new aggregate value — pure but rarely |
| 171 | 171 | // duplicate; include for completeness. |
| 172 | - InstKind::InsertField(agg, i, v) => mk(81, vec![*agg, *v], *i as i64), | |
| 172 | + InstKind::InsertField(agg, i, v) => mk(81, vec![*agg, *v], *i as i128), | |
| 173 | 173 | |
| 174 | 174 | // Impure / not handled ------------------------------------------ |
| 175 | 175 | InstKind::Load(..) |
src/opt/dep_analysis.rsmodified@@ -102,7 +102,7 @@ pub fn extract_affine( | ||
| 102 | 102 | // Find the instruction that defines this value. |
| 103 | 103 | let inst = find_inst(func, val)?; |
| 104 | 104 | match &inst.kind { |
| 105 | - InstKind::ConstInt(c, _) => Some(AffineExpr::from_const(*c)), | |
| 105 | + InstKind::ConstInt(c, _) => i64::try_from(*c).ok().map(AffineExpr::from_const), | |
| 106 | 106 | |
| 107 | 107 | InstKind::IAdd(a, b) => { |
| 108 | 108 | let ea = extract_affine(func, *a, ivs)?; |
@@ -142,7 +142,7 @@ pub fn extract_affine( | ||
| 142 | 142 | |
| 143 | 143 | fn resolve_const(func: &Function, vid: ValueId) -> Option<i64> { |
| 144 | 144 | let inst = find_inst(func, vid)?; |
| 145 | - if let InstKind::ConstInt(c, _) = &inst.kind { Some(*c) } else { None } | |
| 145 | + if let InstKind::ConstInt(c, _) = &inst.kind { i64::try_from(*c).ok() } else { None } | |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | 148 | fn find_inst(func: &Function, vid: ValueId) -> Option<&Inst> { |
src/opt/gvn.rsmodified@@ -38,7 +38,7 @@ impl Pass for Gvn { | ||
| 38 | 38 | struct Key { |
| 39 | 39 | tag: u32, |
| 40 | 40 | operands: Vec<ValueId>, |
| 41 | - aux: i64, | |
| 41 | + aux: i128, | |
| 42 | 42 | name: Option<String>, |
| 43 | 43 | ty: IrType, |
| 44 | 44 | } |
@@ -269,7 +269,7 @@ fn key_of( | ||
| 269 | 269 | pure_calls: &[PureCallPolicy], |
| 270 | 270 | wrapper_values: &HashMap<ValueId, ValueId>, |
| 271 | 271 | ) -> Option<Key> { |
| 272 | - let mk = |tag: u32, ops: Vec<ValueId>, aux: i64| -> Option<Key> { | |
| 272 | + let mk = |tag: u32, ops: Vec<ValueId>, aux: i128| -> Option<Key> { | |
| 273 | 273 | Some(Key { tag, operands: ops, aux, name: None, ty: inst.ty.clone() }) |
| 274 | 274 | }; |
| 275 | 275 | let mk_named = |tag: u32, name: String| -> Option<Key> { |
@@ -297,13 +297,13 @@ fn key_of( | ||
| 297 | 297 | InstKind::FSqrt(a) => mk(16, vec![remap(*a)], 0), |
| 298 | 298 | InstKind::FPow(a, b) => mk(17, vec![remap(*a), remap(*b)], 0), |
| 299 | 299 | InstKind::ICmp(op, a, b) => { |
| 300 | - let op_val = *op as i64; | |
| 300 | + let op_val = *op as i128; | |
| 301 | 301 | match op { |
| 302 | 302 | CmpOp::Eq | CmpOp::Ne => mk(20, canon(remap(*a), remap(*b)), op_val), |
| 303 | 303 | _ => mk(20, vec![remap(*a), remap(*b)], op_val), |
| 304 | 304 | } |
| 305 | 305 | } |
| 306 | - InstKind::FCmp(op, a, b) => mk(21, vec![remap(*a), remap(*b)], *op as i64), | |
| 306 | + InstKind::FCmp(op, a, b) => mk(21, vec![remap(*a), remap(*b)], *op as i128), | |
| 307 | 307 | InstKind::And(a, b) => mk(30, canon(remap(*a), remap(*b)), 0), |
| 308 | 308 | InstKind::Or(a, b) => mk(31, canon(remap(*a), remap(*b)), 0), |
| 309 | 309 | InstKind::Not(a) => mk(32, vec![remap(*a)], 0), |
@@ -319,16 +319,16 @@ fn key_of( | ||
| 319 | 319 | InstKind::CountTrailingZeros(a) => mk(48, vec![remap(*a)], 0), |
| 320 | 320 | InstKind::PopCount(a) => mk(49, vec![remap(*a)], 0), |
| 321 | 321 | // Conversions. |
| 322 | - InstKind::IntToFloat(a, w) => mk(50, vec![remap(*a)], w.bits() as i64), | |
| 323 | - InstKind::FloatToInt(a, w) => mk(51, vec![remap(*a)], w.bits() as i64), | |
| 324 | - InstKind::FloatExtend(a, w) => mk(52, vec![remap(*a)], w.bits() as i64), | |
| 325 | - InstKind::FloatTrunc(a, w) => mk(53, vec![remap(*a)], w.bits() as i64), | |
| 326 | - InstKind::IntExtend(a, w, s) => mk(54, vec![remap(*a)], w.bits() as i64 * if *s { 1 } else { -1 }), | |
| 327 | - InstKind::IntTrunc(a, w) => mk(55, vec![remap(*a)], w.bits() as i64), | |
| 322 | + InstKind::IntToFloat(a, w) => mk(50, vec![remap(*a)], w.bits() as i128), | |
| 323 | + InstKind::FloatToInt(a, w) => mk(51, vec![remap(*a)], w.bits() as i128), | |
| 324 | + InstKind::FloatExtend(a, w) => mk(52, vec![remap(*a)], w.bits() as i128), | |
| 325 | + InstKind::FloatTrunc(a, w) => mk(53, vec![remap(*a)], w.bits() as i128), | |
| 326 | + InstKind::IntExtend(a, w, s) => mk(54, vec![remap(*a)], (w.bits() as i128) * if *s { 1 } else { -1 }), | |
| 327 | + InstKind::IntTrunc(a, w) => mk(55, vec![remap(*a)], w.bits() as i128), | |
| 328 | 328 | // Constants. |
| 329 | - InstKind::ConstInt(v, w) => mk(60, vec![], *v * 100 + w.bits() as i64), | |
| 330 | - InstKind::ConstFloat(v, w) => mk(61, vec![], ((*v).to_bits() as i64) ^ (w.bits() as i64)), | |
| 331 | - InstKind::ConstBool(v) => mk(62, vec![], *v as i64), | |
| 329 | + InstKind::ConstInt(v, w) => mk(60, vec![], *v * 100 + w.bits() as i128), | |
| 330 | + InstKind::ConstFloat(v, w) => mk(61, vec![], ((*v).to_bits() as i128) ^ (w.bits() as i128)), | |
| 331 | + InstKind::ConstBool(v) => mk(62, vec![], *v as i128), | |
| 332 | 332 | // GlobalAddr. |
| 333 | 333 | InstKind::GlobalAddr(name) => mk_named(70, name.clone()), |
| 334 | 334 | // GEP. |
@@ -359,7 +359,7 @@ fn key_of( | ||
| 359 | 359 | PureArgPolicy::Unsupported => return None, |
| 360 | 360 | } |
| 361 | 361 | } |
| 362 | - mk(90, ops, *idx as i64) | |
| 362 | + mk(90, ops, *idx as i128) | |
| 363 | 363 | } |
| 364 | 364 | // Impure: loads, stores, runtime calls, external calls, alloca — not GVN candidates. |
| 365 | 365 | InstKind::Load(..) | InstKind::Store(..) | InstKind::Alloca(..) |
src/opt/loop_utils.rsmodified@@ -45,7 +45,7 @@ pub fn resolve_const_int(func: &Function, vid: ValueId) -> Option<i64> { | ||
| 45 | 45 | for inst in &block.insts { |
| 46 | 46 | if inst.id == vid { |
| 47 | 47 | if let InstKind::ConstInt(v, _) = inst.kind { |
| 48 | - return Some(v); | |
| 48 | + return i64::try_from(v).ok(); | |
| 49 | 49 | } |
| 50 | 50 | return None; |
| 51 | 51 | } |
src/opt/peel.rsmodified@@ -206,7 +206,7 @@ fn do_peel( | ||
| 206 | 206 | }; |
| 207 | 207 | func.block_mut(clone_latch).insts.push(Inst { |
| 208 | 208 | id: next_init_id, |
| 209 | - kind: InstKind::ConstInt(init_const + stride, iv_width), | |
| 209 | + kind: InstKind::ConstInt((init_const + stride) as i128, iv_width), | |
| 210 | 210 | ty: iv_ty.clone(), |
| 211 | 211 | span: dummy_span, |
| 212 | 212 | }); |
src/opt/return_prop.rsmodified@@ -38,7 +38,7 @@ impl Pass for ReturnPropagate { | ||
| 38 | 38 | |
| 39 | 39 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| 40 | 40 | enum ScalarConst { |
| 41 | - Int(i64, IntWidth), | |
| 41 | + Int(i128, IntWidth), | |
| 42 | 42 | Float(u64, FloatWidth), |
| 43 | 43 | Bool(bool), |
| 44 | 44 | } |
src/opt/strength_reduce.rsmodified@@ -89,7 +89,9 @@ fn collect_int_consts(func: &Function) -> HashMap<ValueId, (i64, IntWidth)> { | ||
| 89 | 89 | for block in &func.blocks { |
| 90 | 90 | for inst in &block.insts { |
| 91 | 91 | if let InstKind::ConstInt(v, w) = inst.kind { |
| 92 | - consts.insert(inst.id, (sext(v, w.bits()), w)); | |
| 92 | + if let Ok(v) = i64::try_from(v) { | |
| 93 | + consts.insert(inst.id, (sext(v, w.bits()), w)); | |
| 94 | + } | |
| 93 | 95 | } |
| 94 | 96 | } |
| 95 | 97 | } |
@@ -320,7 +322,7 @@ impl Pass for StrengthReduce { | ||
| 320 | 322 | let span = func.blocks[bi].insts[ii].span; |
| 321 | 323 | func.blocks[bi].insts.insert(ii, Inst { |
| 322 | 324 | id: kid, |
| 323 | - kind: InstKind::ConstInt(k as i64, int_w), | |
| 325 | + kind: InstKind::ConstInt(k as i128, int_w), | |
| 324 | 326 | ty: IrType::Int(int_w), |
| 325 | 327 | span, |
| 326 | 328 | }); |
src/opt/unroll.rsmodified@@ -583,7 +583,7 @@ fn do_unroll(func: &mut Function, shape: LoopShape) { | ||
| 583 | 583 | if bi == 0 { |
| 584 | 584 | let iv_inst = Inst { |
| 585 | 585 | id: iv_const_id, |
| 586 | - kind: InstKind::ConstInt(iv_val, iv_width), | |
| 586 | + kind: InstKind::ConstInt(iv_val as i128, iv_width), | |
| 587 | 587 | ty: shape.iv_ty.clone(), |
| 588 | 588 | span: dummy_span(), |
| 589 | 589 | }; |
@@ -798,7 +798,7 @@ mod tests { | ||
| 798 | 798 | let lo_val = f.next_value_id(); |
| 799 | 799 | f.block_mut(entry_id).insts.push(Inst { |
| 800 | 800 | id: lo_val, ty: IrType::Int(IntWidth::I64), span: span(), |
| 801 | - kind: InstKind::ConstInt(lo, IntWidth::I64), | |
| 801 | + kind: InstKind::ConstInt(lo as i128, IntWidth::I64), | |
| 802 | 802 | }); |
| 803 | 803 | // alloca for the "array" (just a slot we store into) |
| 804 | 804 | let alloca_val = f.next_value_id(); |
@@ -819,7 +819,7 @@ mod tests { | ||
| 819 | 819 | let hi_val = f.next_value_id(); |
| 820 | 820 | f.block_mut(header_id).insts.push(Inst { |
| 821 | 821 | id: hi_val, ty: IrType::Int(IntWidth::I64), span: span(), |
| 822 | - kind: InstKind::ConstInt(hi, IntWidth::I64), | |
| 822 | + kind: InstKind::ConstInt(hi as i128, IntWidth::I64), | |
| 823 | 823 | }); |
| 824 | 824 | // %cmp = icmp.sle %i, hi |
| 825 | 825 | let cmp_val = f.next_value_id(); |
@@ -885,7 +885,7 @@ mod tests { | ||
| 885 | 885 | assert_eq!(f.blocks.len(), 6, "expected entry + 4 iter blocks + exit"); |
| 886 | 886 | |
| 887 | 887 | // Each iteration block has a ConstInt for that iteration's IV value. |
| 888 | - let all_iv_consts: Vec<i64> = f.blocks.iter() | |
| 888 | + let all_iv_consts: Vec<i128> = f.blocks.iter() | |
| 889 | 889 | .flat_map(|b| b.insts.iter()) |
| 890 | 890 | .filter_map(|i| if let InstKind::ConstInt(v, _) = i.kind { Some(v) } else { None }) |
| 891 | 891 | .collect(); |
src/opt/vectorize.rsmodified@@ -512,7 +512,7 @@ fn ensure_i64_const( | ||
| 512 | 512 | func.register_type(id, ty.clone()); |
| 513 | 513 | func.block_mut(block_id).insts.push(Inst { |
| 514 | 514 | id, |
| 515 | - kind: InstKind::ConstInt(value, IntWidth::I64), | |
| 515 | + kind: InstKind::ConstInt(value as i128, IntWidth::I64), | |
| 516 | 516 | ty, |
| 517 | 517 | span, |
| 518 | 518 | }); |
tests/fixtures/integer16_wide_values.f90added@@ -0,0 +1,12 @@ | ||
| 1 | +module integer16_wide_values_mod | |
| 2 | + implicit none | |
| 3 | + integer(16), save :: big_global = 9223372036854775808_16 | |
| 4 | +end module integer16_wide_values_mod | |
| 5 | + | |
| 6 | +program integer16_wide_values | |
| 7 | + use integer16_wide_values_mod | |
| 8 | + implicit none | |
| 9 | + integer(16) :: big_local | |
| 10 | + | |
| 11 | + big_local = 170141183460469231731687303715884105727_16 | |
| 12 | +end program integer16_wide_values | |
tests/i128_ir.rsmodified@@ -41,3 +41,31 @@ fn integer16_lowers_to_i128_in_raw_ir() { | ||
| 41 | 41 | ir |
| 42 | 42 | ); |
| 43 | 43 | } |
| 44 | + | |
| 45 | +#[test] | |
| 46 | +fn integer16_preserves_values_beyond_i64_in_ir_and_globals() { | |
| 47 | + let ir = capture_text( | |
| 48 | + CaptureRequest { | |
| 49 | + input: fixture("integer16_wide_values.f90"), | |
| 50 | + requested: BTreeSet::from([Stage::Ir]), | |
| 51 | + opt_level: OptLevel::O0, | |
| 52 | + }, | |
| 53 | + Stage::Ir, | |
| 54 | + ); | |
| 55 | + | |
| 56 | + assert!( | |
| 57 | + ir.contains("9223372036854775808"), | |
| 58 | + "raw IR should preserve the wide kind-16 global initializer:\n{}", | |
| 59 | + ir | |
| 60 | + ); | |
| 61 | + assert!( | |
| 62 | + ir.contains("170141183460469231731687303715884105727"), | |
| 63 | + "raw IR should preserve the wide kind-16 local constant:\n{}", | |
| 64 | + ir | |
| 65 | + ); | |
| 66 | + assert!( | |
| 67 | + ir.contains("const_int 170141183460469231731687303715884105727 : i128"), | |
| 68 | + "raw IR should materialize wide local literals as i128 constants:\n{}", | |
| 69 | + ir | |
| 70 | + ); | |
| 71 | +} | |