Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cranelift: bnot.b1 is illegal on x86 #1743

Closed
whitequark opened this issue May 21, 2020 · 9 comments · Fixed by #1744
Closed

Cranelift: bnot.b1 is illegal on x86 #1743

whitequark opened this issue May 21, 2020 · 9 comments · Fixed by #1744
Labels
bug Incorrect behavior in the current implementation that needs fixing cranelift Issues related to the Cranelift code generator

Comments

@whitequark
Copy link
Contributor

While looking into another issue I minimized the following testcase, which produces invalid IR:

target x86_64

function u0:323() system_v {
block0:
    v221 = bconst.b1 false
    v222 = bconst.b1 false
    v223 = bnot v221
    v224 = band v223, v222
    trap unreachable
}
[-]                                 v223 = bnot v221
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; error: inst2: v223 is a real GPR value defined by a ghost instruction

It seems to me that it should work but I don't understand what's the missing legalization or selection rule is in this case. @iximeow?

@whitequark whitequark added bug Incorrect behavior in the current implementation that needs fixing cranelift Issues related to the Cranelift code generator labels May 21, 2020
@whitequark whitequark changed the title Cranelift: bnot.b1 is illegal Cranelift: bnot.b1 is illegal on x86_64 May 21, 2020
@whitequark whitequark changed the title Cranelift: bnot.b1 is illegal on x86_64 Cranelift: bnot.b1 is illegal on x86 May 21, 2020
@github-actions
Copy link

Subscribe to Label Action

cc @bnjbvr

This issue or pull request has been labeled: "cranelift"

Thus the following users have been cc'd because of the following labels:

  • bnjbvr: cranelift

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@whitequark
Copy link
Contributor Author

whitequark commented May 21, 2020

I've tried legalizing it like this but it doesn't do anything:

--- a/cranelift/codegen/meta/src/shared/legalize.rs
+++ b/cranelift/codegen/meta/src/shared/legalize.rs
@@ -5,6 +5,7 @@ use crate::cdsl::xform::{TransformGroupBuilder, TransformGroups};
 use crate::shared::immediates::Immediates;
 use crate::shared::types::Float::{F32, F64};
 use crate::shared::types::Int::{I128, I16, I32, I64, I8};
+use crate::shared::types::Bool::B1;
 use cranelift_codegen_shared::condcodes::{CondCode, IntCC};
 
 #[allow(clippy::many_single_char_names, clippy::cognitive_complexity)]
@@ -396,6 +397,14 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
         );
     }
 
+    widen.legalize(
+        def!(a = bnot.B1(b)),
+        vec![
+            def!(x = bint.I32(b)),
+            def!(a = icmp_imm.I32(intcc_eq, x, Literal::constant(&imm.uimm32, 0)))
+        ]
+    );
+
     // Widen instructions with one input operand.
     for &op in &[bnot, popcnt] {
         for &int_ty in &[I8, I16] {

@bjorn3
Copy link
Contributor

bjorn3 commented May 21, 2020

You can try expand instead of widen.

@whitequark
Copy link
Contributor Author

Tried that, it breaks with a really strange message:

error[E0425]: cannot find value `typeof_x` in this scope
   --> /home/whitequark/Projects/wasmtime/target/debug/build/cranelift-codegen-ca1b406eb4035fa6/out/legalizer.rs:195:68
    |
195 |                 let predicate = predicate && TYPE_SETS[0].contains(typeof_x);
    |                                                                    ^^^^^^^^ help: a local variable with a similar name exists: `typeof_a`

error[E0425]: cannot find value `typeof_x` in this scope
   --> /home/whitequark/Projects/wasmtime/target/debug/build/cranelift-codegen-ca1b406eb4035fa6/out/legalizer.rs:197:46
    |
197 |                     let y = pos.ins().iconst(typeof_x, -1);
    |                                              ^^^^^^^^ help: a local variable with a similar name exists: `typeof_a`

error[E0425]: cannot find value `x` in this scope
   --> /home/whitequark/Projects/wasmtime/target/debug/build/cranelift-codegen-ca1b406eb4035fa6/out/legalizer.rs:198:61
    |
198 |                     let a = pos.func.dfg.replace(inst).bxor(x, y);
    |                                                             ^ help: a local variable with a similar name exists: `a`

@iximeow
Copy link
Contributor

iximeow commented May 21, 2020

I think that entirely confused the legalizer codegen :D I'd expect the Expand bnot using xor bit in the shared legalizer to cover this case:

    //# Expand bnot using xor.
    let minus_one = Literal::constant(&imm.imm64, -1);
    expand.legalize(
        def!(a = bnot(x)),
        vec![def!(y = iconst(minus_one)), def!(a = bxor(x, y))],
    );

I'm a little at a loss as to why this doesn't apply.

That said, adding a direct encoding for B1 to x86 does make your test pass:

diff --git a/cranelift/codegen/meta/src/isa/x86/encodings.rs b/cranelift/codegen/meta/src/isa/x86/encodings.rs
index 7863e2bd8..9f1517253 100644
--- a/cranelift/codegen/meta/src/isa/x86/encodings.rs
+++ b/cranelift/codegen/meta/src/isa/x86/encodings.rs
@@ -1454,6 +1454,7 @@ fn define_alu(
     // x86 has a bitwise not instruction NOT.
     e.enc_i32_i64(bnot, rec_ur.opcodes(&NOT).rrr(2));
     e.enc_b32_b64(bnot, rec_ur.opcodes(&NOT).rrr(2));
+    e.enc_both(bnot.bind(B1), rec_ur.opcodes(&NOT).rrr(2));
 
     // Also add a `b1` encodings for the logic instructions.
     // TODO: Should this be done with 8-bit instructions? It would improve partial register

whitequark added a commit to whitequark/wasmtime that referenced this issue May 21, 2020
whitequark added a commit to whitequark/wasmtime that referenced this issue May 21, 2020
Fixes bytecodealliance#1743.

Co-authored-by: iximeow <git@iximeow.net>
@iximeow
Copy link
Contributor

iximeow commented May 21, 2020

I'm a little at a loss as to why this doesn't apply.

Theory: the integer immediate forbids this legalization from applying for an incompatible B1 operand?

@abrown
Copy link
Contributor

abrown commented May 22, 2020

I was just looking at this but because of other problems: B1s are going to look in the expand_flags transform group for legalizations, https://github.com/bytecodealliance/wasmtime/blob/master/cranelift/codegen/meta/src/isa/x86/mod.rs#L40-L59. If it can't find it there, there is no "look in the next transform group" logic so it will just fail.

@iximeow
Copy link
Contributor

iximeow commented May 22, 2020

expand_flags ought to be chained with expand rules afterward:

let mut expand_flags = TransformGroupBuilder::new(
"expand_flags",
r#"
Instruction expansions for architectures with flags.
Expand some instructions using CPU flags, then fall back to the normal
expansions. Not all architectures support CPU flags, so these patterns
are kept separate.
"#,
)
.chain_with(expand_id);

x86_expand is then chained to expand_flags later downstream:

let mut group = TransformGroupBuilder::new(
"x86_expand",
r#"
Legalize instructions by expansion.
Use x86-specific instructions if needed."#,
)
.isa("x86")
.chain_with(shared.transform_groups.by_name("expand_flags").id);

so I'm actually more confused at B1 types being expand_flags rather than x86_expand :(

@abrown
Copy link
Contributor

abrown commented May 22, 2020

Ah, I think you're right: there's chaining for the DSL legalizations (I think?) but not for the custom functions?

whitequark added a commit to whitequark/wasmtime that referenced this issue May 22, 2020
Fixes bytecodealliance#1743.

Co-authored-by: iximeow <git@iximeow.net>
whitequark added a commit to whitequark/wasmtime that referenced this issue May 22, 2020
Fixes bytecodealliance#1743.

Co-authored-by: iximeow <git@iximeow.net>
whitequark added a commit to whitequark/wasmtime that referenced this issue May 22, 2020
Fixes bytecodealliance#1743.

Co-authored-by: iximeow <git@iximeow.net>
whitequark added a commit to whitequark/wasmtime that referenced this issue May 28, 2020
Fixes bytecodealliance#1743.

Co-authored-by: iximeow <git@iximeow.net>
whitequark added a commit to whitequark/wasmtime that referenced this issue May 28, 2020
Fixes bytecodealliance#1743.

Co-authored-by: iximeow <git@iximeow.net>
abrown pushed a commit that referenced this issue May 28, 2020
Fixes #1743.

Co-authored-by: iximeow <git@iximeow.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Incorrect behavior in the current implementation that needs fixing cranelift Issues related to the Cranelift code generator
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants