feilongjiang added the bug label to Issue #8380.
feilongjiang opened issue #8380:
When I run PCC on PloyBenchC, I get the following error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
After adding
WASMTIME_LOG=trace
, the failure was actually caused by the following facts checking:TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: lea 71072(%v299), %v2904l TRACE cranelift_codegen::isa::x64::pcc: compute_addr: Real(ImmReg { simm32: 71072, base: v299, flags: MemFlags { bits: 1921 } }), bits: 32 TRACE cranelift_codegen::machinst::pcc: get_fact_or_default: reg v299 -> Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: base = Range { bit_width: 64, min: 8, max: 8 } TRACE cranelift_codegen::ir::pcc: add: Range { bit_width: 64, min: 8, max: 8 } + Range { bit_width: 32, min: 71072, max: 71072 } -> None, add_width: 32 TRACE cranelift_codegen::machinst::pcc: clamp_range: fact None from 32 to 64 TRACE cranelift_codegen::machinst::pcc: -> clamping to Range { bit_width: 64, min: 0, max: 4294967295 } TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 0, max: 4294967295 }) subsumes stated fact Some(Range { bit_width: 64, min: 71080, max: 71080 }) INFO cranelift_codegen::ir::pcc: Error checking instruction: lea 71072(%v299), %v2904l Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Here are the problem facts:
Range { bit_width: 64, min: 8, max: 8 } Range { bit_width: 32, min: 71072, max: 71072 }
which have different
bit_width
, adding these two facts return aNone
fact. And finallycheck_subsumes_optionals
returns anUnsupportedFact
error.The following IRs are suspicious:
block9: v4339 ! range(64, 0xea28, 0xea28) = iconst.i32 0xea28 v2858 ! range(64, 0x8, 0x8) = iconst.i32 8 v4406 ! range(64, 0x115a0, 0x115a0) = iconst.i32 0x0001_15a0 v4407 ! range(64, 0x115a8, 0x115a8) = iadd v4406, v2858 ; v4406 = 0x0001_15a0, v2858 = 8
they are all
iconst.i32
type but have a 64-bit fact range.
After digging in, I think it may introduced by https://github.com/bytecodealliance/wasmtime/pull/8173,attach_constant_fact
creates facts for constants by adding a 64-bit fact regardless of the constant type.Test Case
PolybenchC 2mm
Steps to Reproduce
First, compile 2mm into wasm with wasi-sdk:
/opt/wasi-sdk/bin/clang -O3 -I utilities -I linear-algebra/kernels/2mm \ utilities/polybench.c linear-algebra/kernels/2mm/2mm.c \ -Wl,--export=__heap_base -Wl,--export=__data_end \ -Wl,--export=malloc -Wl,--export=free \ -DPOLYBENCH_TIME -o out/2mm.wasm \ -D_WASI_EMULATED_PROCESS_CLOCKS
Second, run the
2mm.wasm
with PCC checking enabled:~/workspace/wasmtime/target/debug/wasmtime compile -Cpcc=y,parallel-compilation=n 2mm.wasm
- TODO: first, ...
- TODO: second, ...
- Etc...
Expected Results
PCC facts check passed without error.
Actual Results
Error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Versions and Environment
Wasmtime version or commit: latest commit on the
main
branch (commit id: d53d078)Operating system: Ubuntu 22.04 LTS
Architecture: x86_64
Extra Info
With the following patch, I can pass the PCC check without error. If it is the root cause, I would like to create a PR to fix that.
@@ -485,7 +487,7 @@ where /// Helper to propagate facts on constant values: if PCC is /// enabled, then unconditionally add a fact attesting to the /// Value's concrete value. - fn attach_constant_fact(&mut self, inst: Inst, value: Value) { + fn attach_constant_fact(&mut self, inst: Inst, value: Value, ty: Type) { if self.flags.enable_pcc() { if let InstructionData::UnaryImm { opcode: Opcode::Iconst, @@ -493,7 +495,9 @@ where } = self.func.dfg.insts[inst] { let imm: i64 = imm.into(); - self.func.dfg.facts[value] = Some(Fact::constant(64, imm as u64)); + let fact = Some(Fact::constant(ty.bits().try_into().unwrap(), imm as u64)); + self.func.dfg.facts[value] = fact; } } }
feilongjiang edited issue #8380:
When I run PCC on PloyBenchC, I get the following error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
After adding
WASMTIME_LOG=trace
, the failure was actually caused by the following facts checking:TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: lea 71072(%v299), %v2904l TRACE cranelift_codegen::isa::x64::pcc: compute_addr: Real(ImmReg { simm32: 71072, base: v299, flags: MemFlags { bits: 1921 } }), bits: 32 TRACE cranelift_codegen::machinst::pcc: get_fact_or_default: reg v299 -> Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: base = Range { bit_width: 64, min: 8, max: 8 } TRACE cranelift_codegen::ir::pcc: add: Range { bit_width: 64, min: 8, max: 8 } + Range { bit_width: 32, min: 71072, max: 71072 } -> None, add_width: 32 TRACE cranelift_codegen::machinst::pcc: clamp_range: fact None from 32 to 64 TRACE cranelift_codegen::machinst::pcc: -> clamping to Range { bit_width: 64, min: 0, max: 4294967295 } TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 0, max: 4294967295 }) subsumes stated fact Some(Range { bit_width: 64, min: 71080, max: 71080 }) INFO cranelift_codegen::ir::pcc: Error checking instruction: lea 71072(%v299), %v2904l Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Here are the problem facts:
Range { bit_width: 64, min: 8, max: 8 } Range { bit_width: 32, min: 71072, max: 71072 }
which have different
bit_width
, adding these two facts return aNone
fact. And finallycheck_subsumes_optionals
returns anUnsupportedFact
error.According to the trace log, I find the following IRs are suspicious:
block9: v4339 ! range(64, 0xea28, 0xea28) = iconst.i32 0xea28 v2858 ! range(64, 0x8, 0x8) = iconst.i32 8 v4406 ! range(64, 0x115a0, 0x115a0) = iconst.i32 0x0001_15a0 v4407 ! range(64, 0x115a8, 0x115a8) = iadd v4406, v2858 ; v4406 = 0x0001_15a0, v2858 = 8
they are all
iconst.i32
type but have a 64-bit fact range.
After digging in, I think it may introduced by https://github.com/bytecodealliance/wasmtime/pull/8173,attach_constant_fact
creates facts for constants by adding a 64-bit fact regardless of the constant type.Test Case
PolybenchC 2mm
Steps to Reproduce
First, compile 2mm into wasm with wasi-sdk:
/opt/wasi-sdk/bin/clang -O3 -I utilities -I linear-algebra/kernels/2mm \ utilities/polybench.c linear-algebra/kernels/2mm/2mm.c \ -Wl,--export=__heap_base -Wl,--export=__data_end \ -Wl,--export=malloc -Wl,--export=free \ -DPOLYBENCH_TIME -o out/2mm.wasm \ -D_WASI_EMULATED_PROCESS_CLOCKS
Second, run the
2mm.wasm
with PCC checking enabled:~/workspace/wasmtime/target/debug/wasmtime compile -Cpcc=y,parallel-compilation=n 2mm.wasm
- TODO: first, ...
- TODO: second, ...
- Etc...
Expected Results
PCC facts check passed without error.
Actual Results
Error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Versions and Environment
Wasmtime version or commit: latest commit on the
main
branch (commit id: d53d078)Operating system: Ubuntu 22.04 LTS
Architecture: x86_64
Extra Info
With the following patch, I can pass the PCC check without error. If it is the root cause, I would like to create a PR to fix that.
@@ -485,7 +487,7 @@ where /// Helper to propagate facts on constant values: if PCC is /// enabled, then unconditionally add a fact attesting to the /// Value's concrete value. - fn attach_constant_fact(&mut self, inst: Inst, value: Value) { + fn attach_constant_fact(&mut self, inst: Inst, value: Value, ty: Type) { if self.flags.enable_pcc() { if let InstructionData::UnaryImm { opcode: Opcode::Iconst, @@ -493,7 +495,9 @@ where } = self.func.dfg.insts[inst] { let imm: i64 = imm.into(); - self.func.dfg.facts[value] = Some(Fact::constant(64, imm as u64)); + let fact = Some(Fact::constant(ty.bits().try_into().unwrap(), imm as u64)); + self.func.dfg.facts[value] = fact; } } }
feilongjiang edited issue #8380:
When I run PCC on PloyBenchC, I get the following error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
After adding
WASMTIME_LOG=trace
, the failure was actually caused by the following facts checking:TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: lea 71072(%v299), %v2904l TRACE cranelift_codegen::isa::x64::pcc: compute_addr: Real(ImmReg { simm32: 71072, base: v299, flags: MemFlags { bits: 1921 } }), bits: 32 TRACE cranelift_codegen::machinst::pcc: get_fact_or_default: reg v299 -> Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: base = Range { bit_width: 64, min: 8, max: 8 } TRACE cranelift_codegen::ir::pcc: add: Range { bit_width: 64, min: 8, max: 8 } + Range { bit_width: 32, min: 71072, max: 71072 } -> None, add_width: 32 TRACE cranelift_codegen::machinst::pcc: clamp_range: fact None from 32 to 64 TRACE cranelift_codegen::machinst::pcc: -> clamping to Range { bit_width: 64, min: 0, max: 4294967295 } TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 0, max: 4294967295 }) subsumes stated fact Some(Range { bit_width: 64, min: 71080, max: 71080 }) INFO cranelift_codegen::ir::pcc: Error checking instruction: lea 71072(%v299), %v2904l Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Here are the problem facts:
Range { bit_width: 64, min: 8, max: 8 } Range { bit_width: 32, min: 71072, max: 71072 }
which have different
bit_width
, adding these two facts return aNone
fact. And finallycheck_subsumes_optionals
returns anUnsupportedFact
error.According to the trace log, I find the following IRs are suspicious:
block9: v4339 ! range(64, 0xea28, 0xea28) = iconst.i32 0xea28 v2858 ! range(64, 0x8, 0x8) = iconst.i32 8 v4406 ! range(64, 0x115a0, 0x115a0) = iconst.i32 0x0001_15a0 v4407 ! range(64, 0x115a8, 0x115a8) = iadd v4406, v2858 ; v4406 = 0x0001_15a0, v2858 = 8
they are all
iconst.i32
type but have a 64-bit fact range.
After digging in, I think it may introduced by https://github.com/bytecodealliance/wasmtime/pull/8173,attach_constant_fact
creates facts for constants by adding a 64-bit fact regardless of the constant type.Test Case
PolybenchC 2mm
Steps to Reproduce
First, compile 2mm into wasm with wasi-sdk:
/opt/wasi-sdk/bin/clang -O3 -I utilities -I linear-algebra/kernels/2mm \ utilities/polybench.c linear-algebra/kernels/2mm/2mm.c \ -Wl,--export=__heap_base -Wl,--export=__data_end \ -Wl,--export=malloc -Wl,--export=free \ -DPOLYBENCH_TIME -o out/2mm.wasm \ -D_WASI_EMULATED_PROCESS_CLOCKS
Second, run the
2mm.wasm
with PCC checking enabled:~/workspace/wasmtime/target/debug/wasmtime compile -Cpcc=y,parallel-compilation=n 2mm.wasm
Expected Results
PCC facts check passed without error.
Actual Results
Error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Versions and Environment
Wasmtime version or commit: latest commit on the
main
branch (commit id: d53d078)Operating system: Ubuntu 22.04 LTS
Architecture: x86_64
Extra Info
With the following patch, I can pass the PCC check without error. If it is the root cause, I would like to create a PR to fix that.
@@ -485,7 +487,7 @@ where /// Helper to propagate facts on constant values: if PCC is /// enabled, then unconditionally add a fact attesting to the /// Value's concrete value. - fn attach_constant_fact(&mut self, inst: Inst, value: Value) { + fn attach_constant_fact(&mut self, inst: Inst, value: Value, ty: Type) { if self.flags.enable_pcc() { if let InstructionData::UnaryImm { opcode: Opcode::Iconst, @@ -493,7 +495,9 @@ where } = self.func.dfg.insts[inst] { let imm: i64 = imm.into(); - self.func.dfg.facts[value] = Some(Fact::constant(64, imm as u64)); + let fact = Some(Fact::constant(ty.bits().try_into().unwrap(), imm as u64)); + self.func.dfg.facts[value] = fact; } } }
feilongjiang edited issue #8380:
When I run PCC on PloyBenchC, I get the following error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
After adding
WASMTIME_LOG=trace
, the failure was actually caused by the following facts checking:TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 59944, max: 59944 }) subsumes stated fact Some(Range { bit_width: 64, min: 59944, max: 59944 }) TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: movl $8, %v2905l TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 8, max: 8 }) subsumes stated fact Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: lea 71072(%v299), %v2904l TRACE cranelift_codegen::isa::x64::pcc: compute_addr: Real(ImmReg { simm32: 71072, base: v299, flags: MemFlags { bits: 1921 } }), bits: 32 TRACE cranelift_codegen::machinst::pcc: get_fact_or_default: reg v299 -> Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: base = Range { bit_width: 64, min: 8, max: 8 } TRACE cranelift_codegen::ir::pcc: add: Range { bit_width: 64, min: 8, max: 8 } + Range { bit_width: 32, min: 71072, max: 71072 } -> None, add_width: 32 TRACE cranelift_codegen::machinst::pcc: clamp_range: fact None from 32 to 64 TRACE cranelift_codegen::machinst::pcc: -> clamping to Range { bit_width: 64, min: 0, max: 4294967295 } TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 0, max: 4294967295 }) subsumes stated fact Some(Range { bit_width: 64, min: 71080, max: 71080 }) INFO cranelift_codegen::ir::pcc: Error checking instruction: lea 71072(%v299), %v2904l Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Here are the problem facts:
Range { bit_width: 64, min: 8, max: 8 } Range { bit_width: 32, min: 71072, max: 71072 }
which have different
bit_width
, adding these two facts return aNone
fact. And finallycheck_subsumes_optionals
returns anUnsupportedFact
error.According to the trace log, I find the following IRs are suspicious:
block9: v4339 ! range(64, 0xea28, 0xea28) = iconst.i32 0xea28 v2858 ! range(64, 0x8, 0x8) = iconst.i32 8 v4406 ! range(64, 0x115a0, 0x115a0) = iconst.i32 0x0001_15a0 v4407 ! range(64, 0x115a8, 0x115a8) = iadd v4406, v2858 ; v4406 = 0x0001_15a0, v2858 = 8
they are all
iconst.i32
type but have a 64-bit fact range.
After digging in, I think it may introduced by https://github.com/bytecodealliance/wasmtime/pull/8173,attach_constant_fact
creates facts for constants by adding a 64-bit fact regardless of the constant type.Test Case
PolybenchC 2mm
Steps to Reproduce
First, compile 2mm into wasm with wasi-sdk:
/opt/wasi-sdk/bin/clang -O3 -I utilities -I linear-algebra/kernels/2mm \ utilities/polybench.c linear-algebra/kernels/2mm/2mm.c \ -Wl,--export=__heap_base -Wl,--export=__data_end \ -Wl,--export=malloc -Wl,--export=free \ -DPOLYBENCH_TIME -o out/2mm.wasm \ -D_WASI_EMULATED_PROCESS_CLOCKS
Second, run the
2mm.wasm
with PCC checking enabled:~/workspace/wasmtime/target/debug/wasmtime compile -Cpcc=y,parallel-compilation=n 2mm.wasm
Expected Results
PCC facts check passed without error.
Actual Results
Error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Versions and Environment
Wasmtime version or commit: latest commit on the
main
branch (commit id: d53d078)Operating system: Ubuntu 22.04 LTS
Architecture: x86_64
Extra Info
With the following patch, I can pass the PCC check without error. If it is the root cause, I would like to create a PR to fix that.
@@ -485,7 +487,7 @@ where /// Helper to propagate facts on constant values: if PCC is /// enabled, then unconditionally add a fact attesting to the /// Value's concrete value. - fn attach_constant_fact(&mut self, inst: Inst, value: Value) { + fn attach_constant_fact(&mut self, inst: Inst, value: Value, ty: Type) { if self.flags.enable_pcc() { if let InstructionData::UnaryImm { opcode: Opcode::Iconst, @@ -493,7 +495,9 @@ where } = self.func.dfg.insts[inst] { let imm: i64 = imm.into(); - self.func.dfg.facts[value] = Some(Fact::constant(64, imm as u64)); + let fact = Some(Fact::constant(ty.bits().try_into().unwrap(), imm as u64)); + self.func.dfg.facts[value] = fact; } } }
feilongjiang edited issue #8380:
When I run PCC on PloyBenchC, I get the following error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
After adding
WASMTIME_LOG=trace
, the failure was actually caused by the following facts checking:TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: movl $59944, %v2906l TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 59944, max: 59944 }) subsumes stated fact Some(Range { bit_width: 64, min: 59944, max: 59944 }) TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: movl $8, %v2905l TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 8, max: 8 }) subsumes stated fact Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: lea 71072(%v299), %v2904l TRACE cranelift_codegen::isa::x64::pcc: compute_addr: Real(ImmReg { simm32: 71072, base: v299, flags: MemFlags { bits: 1921 } }), bits: 32 TRACE cranelift_codegen::machinst::pcc: get_fact_or_default: reg v299 -> Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: base = Range { bit_width: 64, min: 8, max: 8 } TRACE cranelift_codegen::ir::pcc: add: Range { bit_width: 64, min: 8, max: 8 } + Range { bit_width: 32, min: 71072, max: 71072 } -> None, add_width: 32 TRACE cranelift_codegen::machinst::pcc: clamp_range: fact None from 32 to 64 TRACE cranelift_codegen::machinst::pcc: -> clamping to Range { bit_width: 64, min: 0, max: 4294967295 } TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 0, max: 4294967295 }) subsumes stated fact Some(Range { bit_width: 64, min: 71080, max: 71080 }) INFO cranelift_codegen::ir::pcc: Error checking instruction: lea 71072(%v299), %v2904l Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Here are the problem facts:
Range { bit_width: 64, min: 8, max: 8 } Range { bit_width: 32, min: 71072, max: 71072 }
which have different
bit_width
, adding these two facts return aNone
fact. And finallycheck_subsumes_optionals
returns anUnsupportedFact
error.According to the trace log, I find the following IRs are suspicious:
block9: v4339 ! range(64, 0xea28, 0xea28) = iconst.i32 0xea28 v2858 ! range(64, 0x8, 0x8) = iconst.i32 8 v4406 ! range(64, 0x115a0, 0x115a0) = iconst.i32 0x0001_15a0 v4407 ! range(64, 0x115a8, 0x115a8) = iadd v4406, v2858 ; v4406 = 0x0001_15a0, v2858 = 8
they are all
iconst.i32
type but have a 64-bit fact range.
After digging in, I think it may introduced by https://github.com/bytecodealliance/wasmtime/pull/8173,attach_constant_fact
creates facts for constants by adding a 64-bit fact regardless of the constant type.Test Case
PolybenchC 2mm
Steps to Reproduce
First, compile 2mm into wasm with wasi-sdk:
/opt/wasi-sdk/bin/clang -O3 -I utilities -I linear-algebra/kernels/2mm \ utilities/polybench.c linear-algebra/kernels/2mm/2mm.c \ -Wl,--export=__heap_base -Wl,--export=__data_end \ -Wl,--export=malloc -Wl,--export=free \ -DPOLYBENCH_TIME -o out/2mm.wasm \ -D_WASI_EMULATED_PROCESS_CLOCKS
Second, run the
2mm.wasm
with PCC checking enabled:~/workspace/wasmtime/target/debug/wasmtime compile -Cpcc=y,parallel-compilation=n 2mm.wasm
Expected Results
PCC facts check passed without error.
Actual Results
Error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Versions and Environment
Wasmtime version or commit: latest commit on the
main
branch (commit id: d53d078)Operating system: Ubuntu 22.04 LTS
Architecture: x86_64
Extra Info
With the following patch, I can pass the PCC check without error. If it is the root cause, I would like to create a PR to fix that.
@@ -485,7 +487,7 @@ where /// Helper to propagate facts on constant values: if PCC is /// enabled, then unconditionally add a fact attesting to the /// Value's concrete value. - fn attach_constant_fact(&mut self, inst: Inst, value: Value) { + fn attach_constant_fact(&mut self, inst: Inst, value: Value, ty: Type) { if self.flags.enable_pcc() { if let InstructionData::UnaryImm { opcode: Opcode::Iconst, @@ -493,7 +495,9 @@ where } = self.func.dfg.insts[inst] { let imm: i64 = imm.into(); - self.func.dfg.facts[value] = Some(Fact::constant(64, imm as u64)); + let fact = Some(Fact::constant(ty.bits().try_into().unwrap(), imm as u64)); + self.func.dfg.facts[value] = fact; } } }
feilongjiang edited issue #8380:
When I run PCC checks on PloyBenchC, I get the following error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
After adding
WASMTIME_LOG=trace
, the failure was actually caused by the following facts checking:TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: movl $59944, %v2906l TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 59944, max: 59944 }) subsumes stated fact Some(Range { bit_width: 64, min: 59944, max: 59944 }) TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: movl $8, %v2905l TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 8, max: 8 }) subsumes stated fact Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: lea 71072(%v299), %v2904l TRACE cranelift_codegen::isa::x64::pcc: compute_addr: Real(ImmReg { simm32: 71072, base: v299, flags: MemFlags { bits: 1921 } }), bits: 32 TRACE cranelift_codegen::machinst::pcc: get_fact_or_default: reg v299 -> Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: base = Range { bit_width: 64, min: 8, max: 8 } TRACE cranelift_codegen::ir::pcc: add: Range { bit_width: 64, min: 8, max: 8 } + Range { bit_width: 32, min: 71072, max: 71072 } -> None, add_width: 32 TRACE cranelift_codegen::machinst::pcc: clamp_range: fact None from 32 to 64 TRACE cranelift_codegen::machinst::pcc: -> clamping to Range { bit_width: 64, min: 0, max: 4294967295 } TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 0, max: 4294967295 }) subsumes stated fact Some(Range { bit_width: 64, min: 71080, max: 71080 }) INFO cranelift_codegen::ir::pcc: Error checking instruction: lea 71072(%v299), %v2904l Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Here are the problem facts:
Range { bit_width: 64, min: 8, max: 8 } Range { bit_width: 32, min: 71072, max: 71072 }
which have different
bit_width
, adding these two facts return aNone
fact. And finallycheck_subsumes_optionals
returns anUnsupportedFact
error.According to the trace log, I find the following IRs are suspicious:
block9: v4339 ! range(64, 0xea28, 0xea28) = iconst.i32 0xea28 v2858 ! range(64, 0x8, 0x8) = iconst.i32 8 v4406 ! range(64, 0x115a0, 0x115a0) = iconst.i32 0x0001_15a0 v4407 ! range(64, 0x115a8, 0x115a8) = iadd v4406, v2858 ; v4406 = 0x0001_15a0, v2858 = 8
they are all
iconst.i32
type but have a 64-bit fact range.
After digging in, I think it may introduced by https://github.com/bytecodealliance/wasmtime/pull/8173,attach_constant_fact
creates facts for constants by adding a 64-bit fact regardless of the constant type.Test Case
PolybenchC 2mm
Steps to Reproduce
First, compile 2mm into wasm with wasi-sdk:
/opt/wasi-sdk/bin/clang -O3 -I utilities -I linear-algebra/kernels/2mm \ utilities/polybench.c linear-algebra/kernels/2mm/2mm.c \ -Wl,--export=__heap_base -Wl,--export=__data_end \ -Wl,--export=malloc -Wl,--export=free \ -DPOLYBENCH_TIME -o out/2mm.wasm \ -D_WASI_EMULATED_PROCESS_CLOCKS
Second, run the
2mm.wasm
with PCC checking enabled:~/workspace/wasmtime/target/debug/wasmtime compile -Cpcc=y,parallel-compilation=n 2mm.wasm
Expected Results
PCC facts check passed without error.
Actual Results
Error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Versions and Environment
Wasmtime version or commit: latest commit on the
main
branch (commit id: d53d078)Operating system: Ubuntu 22.04 LTS
Architecture: x86_64
Extra Info
With the following patch, I can pass the PCC check without error. If it is the root cause, I would like to create a PR to fix that.
@@ -485,7 +487,7 @@ where /// Helper to propagate facts on constant values: if PCC is /// enabled, then unconditionally add a fact attesting to the /// Value's concrete value. - fn attach_constant_fact(&mut self, inst: Inst, value: Value) { + fn attach_constant_fact(&mut self, inst: Inst, value: Value, ty: Type) { if self.flags.enable_pcc() { if let InstructionData::UnaryImm { opcode: Opcode::Iconst, @@ -493,7 +495,9 @@ where } = self.func.dfg.insts[inst] { let imm: i64 = imm.into(); - self.func.dfg.facts[value] = Some(Fact::constant(64, imm as u64)); + let fact = Some(Fact::constant(ty.bits().try_into().unwrap(), imm as u64)); + self.func.dfg.facts[value] = fact; } } }
abrown commented on issue #8380:
cc: @cfallin
feilongjiang commented on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need tomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Any idea about that?
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need tomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Any ideas about that?
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need twomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Any ideas about that?
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need twomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Before https://github.com/bytecodealliance/wasmtime/pull/8173, it will not trigger any error since we only check the range generated by
mov
instructions. After that, the fact range ofmovk
may be an alias of the previousvreg
, which may result in fact range mismatch. E.g.: for the immediate0xFFFFFFFFFFF0BDC0
, the expected fact would beRange { bit_width: 64, min: 0xFFFFFFFFFFF0BDC0, max: 0xFFFFFFFFFFF0BDC0}
, but the actual fact isRange { bit_width: 64, min: 0xFFFFFFFFFFFFBDC0, max: 0xFFFFFFFFFFFFBDC0}
, thensubsume
check would fail.Any ideas about that?
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need twomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Before https://github.com/bytecodealliance/wasmtime/pull/8173, it will not trigger any error since we only check the range generated by
mov
instructions (but incorrect fact range). After that, the fact range ofmovk
may be an alias of the previousvreg
, which may result in fact range mismatch. E.g.: for the immediate0xFFFFFFFFFFF0BDC0
, the expected fact would beRange { bit_width: 64, min: 0xFFFFFFFFFFF0BDC0, max: 0xFFFFFFFFFFF0BDC0}
, but the actual fact isRange { bit_width: 64, min: 0xFFFFFFFFFFFFBDC0, max: 0xFFFFFFFFFFFFBDC0}
, thensubsume
check would fail.Any ideas about that?
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need twomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Before https://github.com/bytecodealliance/wasmtime/pull/8173, it will not trigger any error since we only check the range generated by
mov
instructions (but incorrect fact range). After that, the fact range ofmovk
may be an alias of the previousvreg
, which may result in fact range mismatch. E.g.: for the immediate0xFFFFFFFFFFF0BDC0
, the expected fact would beRange { bit_width: 64, min: 0xFFFFFFFFFFF0BDC0, max: 0xFFFFFFFFFFF0BDC0}
, but the actual fact isRange { bit_width: 64, min: 0xFFFFFFFFFFFFBDC0, max: 0xFFFFFFFFFFFFBDC0}
, thensubsume
check would fail too.Any ideas about that?
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need twomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Before https://github.com/bytecodealliance/wasmtime/pull/8173, it will not trigger any error since we only check the range generated by
mov
instructions (but incorrect fact range). After that, the fact range ofmovk
may be an alias of the previousvreg
, which may result in fact range mismatch. E.g.: for the immediate0xFFFFFFFFFFF0BDC0
, the expected fact would beRange { bit_width: 64, min: 0xFFFFFFFFFFF0BDC0, max: 0xFFFFFFFFFFF0BDC0}
, but the actual fact isRange { bit_width: 64, min: 0xFFFFFFFFFFFFBDC0, max: 0xFFFFFFFFFFFFBDC0}
, thensubsume
check would fail, too.Any ideas about that?
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need twomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Before https://github.com/bytecodealliance/wasmtime/pull/8173, it will not trigger any error since we only check the range generated by
mov
instructions (but incorrect fact range). After that, the fact range ofmovk
may be an alias of the previousvreg
and be overwritten, which may result in fact range mismatch. E.g.: for the immediate0xFFFFFFFFFFF0BDC0
, the expected fact would beRange { bit_width: 64, min: 0xFFFFFFFFFFF0BDC0, max: 0xFFFFFFFFFFF0BDC0}
, but the actual fact isRange { bit_width: 64, min: 0xFFFFFFFFFFFFBDC0, max: 0xFFFFFFFFFFFFBDC0}
, thensubsume
check would fail, too.Any ideas about that?
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need twomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Before https://github.com/bytecodealliance/wasmtime/pull/8173, it will not trigger any error since we only check the range generated by
mov
instructions (but incorrect fact range). After that, the fact range ofmovk
may be an alias of the previousvreg
and be overwritten, which may result in fact range mismatch. E.g.: for the immediate0xFFFFFFFFFFF0BDC0
, the expected fact would beRange { bit_width: 64, min: 0xFFFFFFFFFFF0BDC0, max: 0xFFFFFFFFFFF0BDC0}
, but the actual fact isRange { bit_width: 64, min: 0xFFFFFFFFFFFFBDC0, max: 0xFFFFFFFFFFFFBDC0}
, thensubsume
check would fail, too.Any ideas about that?
Edit:
Turns out we should also fix the constant passed tocheck_constant
formovk
:diff --git a/cranelift/codegen/src/isa/aarch64/pcc.rs b/cranelift/codegen/src/isa/aarch64/pcc.rs index cdc6ca42e..b2dd95577 100644 --- a/cranelift/codegen/src/isa/aarch64/pcc.rs +++ b/cranelift/codegen/src/isa/aarch64/pcc.rs @@ -305,7 +305,8 @@ pub(crate) fn check( let input = get_fact_or_default(vcode, rn, 64); if let Some(input_constant) = input.as_const(64) { let constant = u64::from(imm.bits) << (imm.shift * 16); - let constant = input_constant | constant; + let mask = 0xFFFF << (imm.shift * 16); + let constant = input_constant & !mask | constant; check_constant(ctx, vcode, rd, 64, constant) } else { check_output(ctx, vcode, rd, &[], |_vcode| {
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need twomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Before https://github.com/bytecodealliance/wasmtime/pull/8173, it will not trigger any error since we only check the range generated by
mov
instructions (but incorrect fact range). After that, the fact range ofmovk
may be an alias of the previousvreg
and be overwritten, which may result in fact range mismatch. E.g.: for the immediate0xFFFFFFFFFFF0BDC0
, the expected fact would beRange { bit_width: 64, min: 0xFFFFFFFFFFF0BDC0, max: 0xFFFFFFFFFFF0BDC0}
, but the actual fact isRange { bit_width: 64, min: 0xFFFFFFFFFFFFBDC0, max: 0xFFFFFFFFFFFFBDC0}
, thensubsume
check would fail, too.Any ideas about that?
Edit:
Turns out we should also update theconstant
passed tocheck_constant
formovk
:diff --git a/cranelift/codegen/src/isa/aarch64/pcc.rs b/cranelift/codegen/src/isa/aarch64/pcc.rs index cdc6ca42e..b2dd95577 100644 --- a/cranelift/codegen/src/isa/aarch64/pcc.rs +++ b/cranelift/codegen/src/isa/aarch64/pcc.rs @@ -305,7 +305,8 @@ pub(crate) fn check( let input = get_fact_or_default(vcode, rn, 64); if let Some(input_constant) = input.as_const(64) { let constant = u64::from(imm.bits) << (imm.shift * 16); - let constant = input_constant | constant; + let mask = 0xFFFF << (imm.shift * 16); + let constant = input_constant & !mask | constant; check_constant(ctx, vcode, rd, 64, constant) } else { check_output(ctx, vcode, rd, &[], |_vcode| {
feilongjiang edited a comment on issue #8380:
Also, find another issue on AArch64 when generating facts for
mov
instructions:
Currently,movk
will generate a fact range by simply orring the oldrunning_value
withimm16 << shift
[1], but to get the correct fact range, maybe we should use the following snippets:let mask = 0xFFFF << shift; running_value &= !mask; running_value |= imm16 << shift;
For example, for immediate
0x9_ffff_ffff
, we need twomov
instructions:Inst 0: movn %v193, #65526, LSL #32 v193 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff) Inst 1: movk %v194, %v193, #0, LSL #48 v194 ! range(64, 0xffff0009ffffffff, 0xffff0009ffffffff)
The first
movn
generates the correct fact range as #7593 merged. But formovk
, it should berange(64, 0x9ffffffff, 0009ffffffff)
since we want to move0x9_ffff_ffff
to the register, right? If the correct fact range isrange(64, 0x9ffffffff, 0x9ffffffff)
, then the latersubsume
check will fail as0xffff0009ffffffff
can not subsume0x9ffffffff
.Before https://github.com/bytecodealliance/wasmtime/pull/8173, it will not trigger any error since we only check the range generated by
mov
instructions (but incorrect fact range). After that, the fact range ofmovk
may be an alias of the previousvreg
and be overwritten, which may result in fact range mismatch. E.g.: for the immediate0xFFFFFFFFFFF0BDC0
, the expected fact would beRange { bit_width: 64, min: 0xFFFFFFFFFFF0BDC0, max: 0xFFFFFFFFFFF0BDC0}
, but the actual fact isRange { bit_width: 64, min: 0xFFFFFFFFFFFFBDC0, max: 0xFFFFFFFFFFFFBDC0}
, thensubsume
check would fail, too.Any ideas about that?
Edit:
Turns out we should also update theconstant
passed tocheck_constant
formovk
:diff --git a/cranelift/codegen/src/isa/aarch64/pcc.rs b/cranelift/codegen/src/isa/aarch64/pcc.rs index cdc6ca42e..b2dd95577 100644 --- a/cranelift/codegen/src/isa/aarch64/pcc.rs +++ b/cranelift/codegen/src/isa/aarch64/pcc.rs @@ -305,7 +305,8 @@ pub(crate) fn check( let input = get_fact_or_default(vcode, rn, 64); if let Some(input_constant) = input.as_const(64) { let constant = u64::from(imm.bits) << (imm.shift * 16); - let constant = input_constant | constant; + let mask = 0xFFFF << (imm.shift * 16); + let constant = input_constant & !mask | constant; check_constant(ctx, vcode, rd, 64, constant) } else { check_output(ctx, vcode, rd, &[], |_vcode| {
cfallin commented on issue #8380:
PCC isn't actively being worked on right now and we expect some issues when we get back to fuzzing it -- thanks for looking at this! I'd be happy to review a PR with a fix if you have one.
jameysharp closed issue #8380:
When I run PCC checks on PloyBenchC, I get the following error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
After adding
WASMTIME_LOG=trace
, the failure was actually caused by the following facts checking:TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: movl $59944, %v2906l TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 59944, max: 59944 }) subsumes stated fact Some(Range { bit_width: 64, min: 59944, max: 59944 }) TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: movl $8, %v2905l TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 8, max: 8 }) subsumes stated fact Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: Checking facts on inst: lea 71072(%v299), %v2904l TRACE cranelift_codegen::isa::x64::pcc: compute_addr: Real(ImmReg { simm32: 71072, base: v299, flags: MemFlags { bits: 1921 } }), bits: 32 TRACE cranelift_codegen::machinst::pcc: get_fact_or_default: reg v299 -> Some(Range { bit_width: 64, min: 8, max: 8 }) TRACE cranelift_codegen::isa::x64::pcc: base = Range { bit_width: 64, min: 8, max: 8 } TRACE cranelift_codegen::ir::pcc: add: Range { bit_width: 64, min: 8, max: 8 } + Range { bit_width: 32, min: 71072, max: 71072 } -> None, add_width: 32 TRACE cranelift_codegen::machinst::pcc: clamp_range: fact None from 32 to 64 TRACE cranelift_codegen::machinst::pcc: -> clamping to Range { bit_width: 64, min: 0, max: 4294967295 } TRACE cranelift_codegen::machinst::pcc: checking if derived fact Some(Range { bit_width: 64, min: 0, max: 4294967295 }) subsumes stated fact Some(Range { bit_width: 64, min: 71080, max: 71080 }) INFO cranelift_codegen::ir::pcc: Error checking instruction: lea 71072(%v299), %v2904l Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Here are the problem facts:
Range { bit_width: 64, min: 8, max: 8 } Range { bit_width: 32, min: 71072, max: 71072 }
which have different
bit_width
, adding these two facts return aNone
fact. And finallycheck_subsumes_optionals
returns anUnsupportedFact
error.According to the trace log, I find the following IRs are suspicious:
block9: v4339 ! range(64, 0xea28, 0xea28) = iconst.i32 0xea28 v2858 ! range(64, 0x8, 0x8) = iconst.i32 8 v4406 ! range(64, 0x115a0, 0x115a0) = iconst.i32 0x0001_15a0 v4407 ! range(64, 0x115a8, 0x115a8) = iadd v4406, v2858 ; v4406 = 0x0001_15a0, v2858 = 8
they are all
iconst.i32
type but have a 64-bit fact range.
After digging in, I think it may introduced by https://github.com/bytecodealliance/wasmtime/pull/8173,attach_constant_fact
creates facts for constants by adding a 64-bit fact regardless of the constant type.Test Case
PolybenchC 2mm
Steps to Reproduce
First, compile 2mm into wasm with wasi-sdk:
/opt/wasi-sdk/bin/clang -O3 -I utilities -I linear-algebra/kernels/2mm \ utilities/polybench.c linear-algebra/kernels/2mm/2mm.c \ -Wl,--export=__heap_base -Wl,--export=__data_end \ -Wl,--export=malloc -Wl,--export=free \ -DPOLYBENCH_TIME -o out/2mm.wasm \ -D_WASI_EMULATED_PROCESS_CLOCKS
Second, run the
2mm.wasm
with PCC checking enabled:~/workspace/wasmtime/target/debug/wasmtime compile -Cpcc=y,parallel-compilation=n 2mm.wasm
Expected Results
PCC facts check passed without error.
Actual Results
Error:
Error: Compilation error: Proof-carrying-code validation error: UnsupportedFact
Versions and Environment
Wasmtime version or commit: latest commit on the
main
branch (commit id: d53d078)Operating system: Ubuntu 22.04 LTS
Architecture: x86_64
Extra Info
With the following patch, I can pass the PCC check without error. If it is the root cause, I would like to create a PR to fix that.
@@ -485,7 +487,7 @@ where /// Helper to propagate facts on constant values: if PCC is /// enabled, then unconditionally add a fact attesting to the /// Value's concrete value. - fn attach_constant_fact(&mut self, inst: Inst, value: Value) { + fn attach_constant_fact(&mut self, inst: Inst, value: Value, ty: Type) { if self.flags.enable_pcc() { if let InstructionData::UnaryImm { opcode: Opcode::Iconst, @@ -493,7 +495,9 @@ where } = self.func.dfg.insts[inst] { let imm: i64 = imm.into(); - self.func.dfg.facts[value] = Some(Fact::constant(64, imm as u64)); + let fact = Some(Fact::constant(ty.bits().try_into().unwrap(), imm as u64)); + self.func.dfg.facts[value] = fact; } } }
jameysharp commented on issue #8380:
Now that #8393 is merged, I'm closing this issue because I assume it's fixed, but if you find more bugs you can open a new issue or re-open this one. Thank you!
Last updated: Dec 23 2024 at 12:05 UTC