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

pulley: Add branch-with-compare-against-immediate #9863

Merged
merged 1 commit into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions cranelift/codegen/src/isa/pulley_shared/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,35 @@
(IfXult32 (src1 XReg) (src2 XReg))
(IfXulteq32 (src1 XReg) (src2 XReg))

(IfXeq32I32 (src1 XReg) (src2 i32))
(IfXneq32I32 (src1 XReg) (src2 i32))
(IfXslt32I32 (src1 XReg) (src2 i32))
(IfXslteq32I32 (src1 XReg) (src2 i32))
(IfXult32I32 (src1 XReg) (src2 u32))
(IfXulteq32I32 (src1 XReg) (src2 u32))
(IfXsgt32I32 (src1 XReg) (src2 i32))
(IfXsgteq32I32 (src1 XReg) (src2 i32))
(IfXugt32I32 (src1 XReg) (src2 u32))
(IfXugteq32I32 (src1 XReg) (src2 u32))

;; Conditionals for comparing two 64-bit registers.
(IfXeq64 (src1 XReg) (src2 XReg))
(IfXneq64 (src1 XReg) (src2 XReg))
(IfXslt64 (src1 XReg) (src2 XReg))
(IfXslteq64 (src1 XReg) (src2 XReg))
(IfXult64 (src1 XReg) (src2 XReg))
(IfXulteq64 (src1 XReg) (src2 XReg))

(IfXeq64I32 (src1 XReg) (src2 i32))
(IfXneq64I32 (src1 XReg) (src2 i32))
(IfXslt64I32 (src1 XReg) (src2 i32))
(IfXslteq64I32 (src1 XReg) (src2 i32))
(IfXult64I32 (src1 XReg) (src2 u32))
(IfXulteq64I32 (src1 XReg) (src2 u32))
(IfXsgt64I32 (src1 XReg) (src2 i32))
(IfXsgteq64I32 (src1 XReg) (src2 i32))
(IfXugt64I32 (src1 XReg) (src2 u32))
(IfXugteq64I32 (src1 XReg) (src2 u32))
)
)

Expand Down
194 changes: 193 additions & 1 deletion cranelift/codegen/src/isa/pulley_shared/inst/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,34 @@ impl Cond {
collector.reg_use(src1);
collector.reg_use(src2);
}

Cond::IfXeq32I32 { src1, src2 }
| Cond::IfXneq32I32 { src1, src2 }
| Cond::IfXslt32I32 { src1, src2 }
| Cond::IfXslteq32I32 { src1, src2 }
| Cond::IfXsgt32I32 { src1, src2 }
| Cond::IfXsgteq32I32 { src1, src2 }
| Cond::IfXeq64I32 { src1, src2 }
| Cond::IfXneq64I32 { src1, src2 }
| Cond::IfXslt64I32 { src1, src2 }
| Cond::IfXslteq64I32 { src1, src2 }
| Cond::IfXsgt64I32 { src1, src2 }
| Cond::IfXsgteq64I32 { src1, src2 } => {
collector.reg_use(src1);
let _: &mut i32 = src2;
}

Cond::IfXult32I32 { src1, src2 }
| Cond::IfXulteq32I32 { src1, src2 }
| Cond::IfXugt32I32 { src1, src2 }
| Cond::IfXugteq32I32 { src1, src2 }
| Cond::IfXult64I32 { src1, src2 }
| Cond::IfXulteq64I32 { src1, src2 }
| Cond::IfXugt64I32 { src1, src2 }
| Cond::IfXugteq64I32 { src1, src2 } => {
collector.reg_use(src1);
let _: &mut u32 = src2;
}
}
}

Expand All @@ -263,7 +291,7 @@ impl Cond {
/// Note that the offset encoded to jump by is filled in as 0 and it's
/// assumed `MachBuffer` will come back and clean it up.
pub fn encode(&self, sink: &mut impl Extend<u8>) {
match self {
match *self {
Cond::If32 { reg } => encode::br_if32(sink, reg, 0),
Cond::IfNot32 { reg } => encode::br_if_not32(sink, reg, 0),
Cond::IfXeq32 { src1, src2 } => encode::br_if_xeq32(sink, src1, src2, 0),
Expand All @@ -278,6 +306,88 @@ impl Cond {
Cond::IfXslteq64 { src1, src2 } => encode::br_if_xslteq64(sink, src1, src2, 0),
Cond::IfXult64 { src1, src2 } => encode::br_if_xult64(sink, src1, src2, 0),
Cond::IfXulteq64 { src1, src2 } => encode::br_if_xulteq64(sink, src1, src2, 0),

Cond::IfXeq32I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xeq32_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xeq32_i32(sink, src1, src2, 0),
},
Cond::IfXneq32I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xneq32_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xneq32_i32(sink, src1, src2, 0),
},
Cond::IfXslt32I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xslt32_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xslt32_i32(sink, src1, src2, 0),
},
Cond::IfXslteq32I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xslteq32_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xslteq32_i32(sink, src1, src2, 0),
},
Cond::IfXsgt32I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xsgt32_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xsgt32_i32(sink, src1, src2, 0),
},
Cond::IfXsgteq32I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xsgteq32_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xsgteq32_i32(sink, src1, src2, 0),
},
Cond::IfXult32I32 { src1, src2 } => match u8::try_from(src2) {
Ok(src2) => encode::br_if_xult32_u8(sink, src1, src2, 0),
Err(_) => encode::br_if_xult32_u32(sink, src1, src2, 0),
},
Cond::IfXulteq32I32 { src1, src2 } => match u8::try_from(src2) {
Ok(src2) => encode::br_if_xulteq32_u8(sink, src1, src2, 0),
Err(_) => encode::br_if_xulteq32_u32(sink, src1, src2, 0),
},
Cond::IfXugt32I32 { src1, src2 } => match u8::try_from(src2) {
Ok(src2) => encode::br_if_xugt32_u8(sink, src1, src2, 0),
Err(_) => encode::br_if_xugt32_u32(sink, src1, src2, 0),
},
Cond::IfXugteq32I32 { src1, src2 } => match u8::try_from(src2) {
Ok(src2) => encode::br_if_xugteq32_u8(sink, src1, src2, 0),
Err(_) => encode::br_if_xugteq32_u32(sink, src1, src2, 0),
},

Cond::IfXeq64I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xeq64_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xeq64_i32(sink, src1, src2, 0),
},
Cond::IfXneq64I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xneq64_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xneq64_i32(sink, src1, src2, 0),
},
Cond::IfXslt64I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xslt64_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xslt64_i32(sink, src1, src2, 0),
},
Cond::IfXslteq64I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xslteq64_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xslteq64_i32(sink, src1, src2, 0),
},
Cond::IfXsgt64I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xsgt64_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xsgt64_i32(sink, src1, src2, 0),
},
Cond::IfXsgteq64I32 { src1, src2 } => match i8::try_from(src2) {
Ok(src2) => encode::br_if_xsgteq64_i8(sink, src1, src2, 0),
Err(_) => encode::br_if_xsgteq64_i32(sink, src1, src2, 0),
},
Cond::IfXult64I32 { src1, src2 } => match u8::try_from(src2) {
Ok(src2) => encode::br_if_xult64_u8(sink, src1, src2, 0),
Err(_) => encode::br_if_xult64_u32(sink, src1, src2, 0),
},
Cond::IfXulteq64I32 { src1, src2 } => match u8::try_from(src2) {
Ok(src2) => encode::br_if_xulteq64_u8(sink, src1, src2, 0),
Err(_) => encode::br_if_xulteq64_u32(sink, src1, src2, 0),
},
Cond::IfXugt64I32 { src1, src2 } => match u8::try_from(src2) {
Ok(src2) => encode::br_if_xugt64_u8(sink, src1, src2, 0),
Err(_) => encode::br_if_xugt64_u32(sink, src1, src2, 0),
},
Cond::IfXugteq64I32 { src1, src2 } => match u8::try_from(src2) {
Ok(src2) => encode::br_if_xugteq64_u8(sink, src1, src2, 0),
Err(_) => encode::br_if_xugteq64_u32(sink, src1, src2, 0),
},
}
}

Expand Down Expand Up @@ -325,6 +435,28 @@ impl Cond {
src1: src2,
src2: src1,
},

Cond::IfXeq32I32 { src1, src2 } => Cond::IfXneq32I32 { src1, src2 },
Cond::IfXneq32I32 { src1, src2 } => Cond::IfXeq32I32 { src1, src2 },
Cond::IfXslt32I32 { src1, src2 } => Cond::IfXsgteq32I32 { src1, src2 },
Cond::IfXslteq32I32 { src1, src2 } => Cond::IfXsgt32I32 { src1, src2 },
Cond::IfXult32I32 { src1, src2 } => Cond::IfXugteq32I32 { src1, src2 },
Cond::IfXulteq32I32 { src1, src2 } => Cond::IfXugt32I32 { src1, src2 },
Cond::IfXsgt32I32 { src1, src2 } => Cond::IfXslteq32I32 { src1, src2 },
Cond::IfXsgteq32I32 { src1, src2 } => Cond::IfXslt32I32 { src1, src2 },
Cond::IfXugt32I32 { src1, src2 } => Cond::IfXulteq32I32 { src1, src2 },
Cond::IfXugteq32I32 { src1, src2 } => Cond::IfXult32I32 { src1, src2 },

Cond::IfXeq64I32 { src1, src2 } => Cond::IfXneq64I32 { src1, src2 },
Cond::IfXneq64I32 { src1, src2 } => Cond::IfXeq64I32 { src1, src2 },
Cond::IfXslt64I32 { src1, src2 } => Cond::IfXsgteq64I32 { src1, src2 },
Cond::IfXslteq64I32 { src1, src2 } => Cond::IfXsgt64I32 { src1, src2 },
Cond::IfXult64I32 { src1, src2 } => Cond::IfXugteq64I32 { src1, src2 },
Cond::IfXulteq64I32 { src1, src2 } => Cond::IfXugt64I32 { src1, src2 },
Cond::IfXsgt64I32 { src1, src2 } => Cond::IfXslteq64I32 { src1, src2 },
Cond::IfXsgteq64I32 { src1, src2 } => Cond::IfXslt64I32 { src1, src2 },
Cond::IfXugt64I32 { src1, src2 } => Cond::IfXulteq64I32 { src1, src2 },
Cond::IfXugteq64I32 { src1, src2 } => Cond::IfXult64I32 { src1, src2 },
}
}
}
Expand Down Expand Up @@ -370,6 +502,66 @@ impl fmt::Display for Cond {
Cond::IfXulteq64 { src1, src2 } => {
write!(f, "if_xulteq64 {}, {}", reg_name(**src1), reg_name(**src2))
}
Cond::IfXeq32I32 { src1, src2 } => {
write!(f, "if_xeq32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXneq32I32 { src1, src2 } => {
write!(f, "if_xneq32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXslt32I32 { src1, src2 } => {
write!(f, "if_xslt32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXslteq32I32 { src1, src2 } => {
write!(f, "if_xslteq32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXsgt32I32 { src1, src2 } => {
write!(f, "if_xsgt32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXsgteq32I32 { src1, src2 } => {
write!(f, "if_xsgteq32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXult32I32 { src1, src2 } => {
write!(f, "if_xult32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXulteq32I32 { src1, src2 } => {
write!(f, "if_xulteq32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXugt32I32 { src1, src2 } => {
write!(f, "if_xugt32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXugteq32I32 { src1, src2 } => {
write!(f, "if_xugteq32_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXeq64I32 { src1, src2 } => {
write!(f, "if_xeq64_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXneq64I32 { src1, src2 } => {
write!(f, "if_xneq64_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXslt64I32 { src1, src2 } => {
write!(f, "if_xslt64_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXslteq64I32 { src1, src2 } => {
write!(f, "if_xslteq64_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXsgt64I32 { src1, src2 } => {
write!(f, "if_xsgt64_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXsgteq64I32 { src1, src2 } => {
write!(f, "if_xsgteq64_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXult64I32 { src1, src2 } => {
write!(f, "if_xult64_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXulteq64I32 { src1, src2 } => {
write!(f, "if_xulteq64_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXugt64I32 { src1, src2 } => {
write!(f, "if_xugt64_i32 {}, {src2}", reg_name(**src1))
}
Cond::IfXugteq64I32 { src1, src2 } => {
write!(f, "if_xugteq64_i32 {}, {src2}", reg_name(**src1))
}
}
}
}
88 changes: 88 additions & 0 deletions cranelift/codegen/src/isa/pulley_shared/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,27 @@
(rule (lower_cond_icmp32 (IntCC.UnsignedGreaterThan) a b) (Cond.IfXult32 b a))
(rule (lower_cond_icmp32 (IntCC.UnsignedGreaterThanOrEqual) a b) (Cond.IfXulteq32 b a))

(rule 1 (lower_cond_icmp32 (IntCC.Equal) a (i32_from_iconst b))
(Cond.IfXeq32I32 a b))
(rule 1 (lower_cond_icmp32 (IntCC.NotEqual) a (i32_from_iconst b))
(Cond.IfXneq32I32 a b))
(rule 1 (lower_cond_icmp32 (IntCC.SignedLessThan) a (i32_from_iconst b))
(Cond.IfXslt32I32 a b))
(rule 1 (lower_cond_icmp32 (IntCC.SignedLessThanOrEqual) a (i32_from_iconst b))
(Cond.IfXslteq32I32 a b))
(rule 1 (lower_cond_icmp32 (IntCC.SignedGreaterThan) a (i32_from_iconst b))
(Cond.IfXsgt32I32 a b))
(rule 1 (lower_cond_icmp32 (IntCC.SignedGreaterThanOrEqual) a (i32_from_iconst b))
(Cond.IfXsgteq32I32 a b))
(rule 1 (lower_cond_icmp32 (IntCC.UnsignedLessThan) a (u32_from_iconst b))
(Cond.IfXult32I32 a b))
(rule 1 (lower_cond_icmp32 (IntCC.UnsignedLessThanOrEqual) a (u32_from_iconst b))
(Cond.IfXulteq32I32 a b))
(rule 1 (lower_cond_icmp32 (IntCC.UnsignedGreaterThan) a (u32_from_iconst b))
(Cond.IfXugt32I32 a b))
(rule 1 (lower_cond_icmp32 (IntCC.UnsignedGreaterThanOrEqual) a (u32_from_iconst b))
(Cond.IfXugteq32I32 a b))

(decl lower_cond_icmp64 (IntCC Value Value) Cond)
(rule (lower_cond_icmp64 (IntCC.Equal) a b) (Cond.IfXeq64 a b))
(rule (lower_cond_icmp64 (IntCC.NotEqual) a b) (Cond.IfXneq64 a b))
Expand All @@ -48,6 +69,27 @@
(rule (lower_cond_icmp64 (IntCC.UnsignedGreaterThan) a b) (Cond.IfXult64 b a))
(rule (lower_cond_icmp64 (IntCC.UnsignedGreaterThanOrEqual) a b) (Cond.IfXulteq64 b a))

(rule 1 (lower_cond_icmp64 (IntCC.Equal) a (i32_from_iconst b))
(Cond.IfXeq64I32 a b))
(rule 1 (lower_cond_icmp64 (IntCC.NotEqual) a (i32_from_iconst b))
(Cond.IfXneq64I32 a b))
(rule 1 (lower_cond_icmp64 (IntCC.SignedLessThan) a (i32_from_iconst b))
(Cond.IfXslt64I32 a b))
(rule 1 (lower_cond_icmp64 (IntCC.SignedLessThanOrEqual) a (i32_from_iconst b))
(Cond.IfXslteq64I32 a b))
(rule 1 (lower_cond_icmp64 (IntCC.SignedGreaterThan) a (i32_from_iconst b))
(Cond.IfXsgt64I32 a b))
(rule 1 (lower_cond_icmp64 (IntCC.SignedGreaterThanOrEqual) a (i32_from_iconst b))
(Cond.IfXsgteq64I32 a b))
(rule 1 (lower_cond_icmp64 (IntCC.UnsignedLessThan) a (u32_from_iconst b))
(Cond.IfXult64I32 a b))
(rule 1 (lower_cond_icmp64 (IntCC.UnsignedLessThanOrEqual) a (u32_from_iconst b))
(Cond.IfXulteq64I32 a b))
(rule 1 (lower_cond_icmp64 (IntCC.UnsignedGreaterThan) a (u32_from_iconst b))
(Cond.IfXugt64I32 a b))
(rule 1 (lower_cond_icmp64 (IntCC.UnsignedGreaterThanOrEqual) a (u32_from_iconst b))
(Cond.IfXugteq64I32 a b))

;; The main control-flow-lowering term: takes a control-flow instruction and
;; target(s) and emits the necessary instructions.
(decl partial lower_branch (Inst MachLabelSlice) Unit)
Expand Down Expand Up @@ -880,6 +922,52 @@
(rule (emit_cond (Cond.IfXult64 src1 src2)) (pulley_xult64 src1 src2))
(rule (emit_cond (Cond.IfXulteq64 src1 src2)) (pulley_xulteq64 src1 src2))

(rule (emit_cond (Cond.IfXeq32I32 src1 src2))
(pulley_xeq32 src1 (imm $I32 (i64_as_u64 (i32_as_i64 src2)))))
(rule (emit_cond (Cond.IfXneq32I32 src1 src2))
(pulley_xneq32 src1 (imm $I32 (i64_as_u64 (i32_as_i64 src2)))))
(rule (emit_cond (Cond.IfXslt32I32 src1 src2))
(pulley_xslt32 src1 (imm $I32 (i64_as_u64 (i32_as_i64 src2)))))
(rule (emit_cond (Cond.IfXslteq32I32 src1 src2))
(pulley_xslteq32 src1 (imm $I32 (i64_as_u64 (i32_as_i64 src2)))))
(rule (emit_cond (Cond.IfXult32I32 src1 src2))
(pulley_xult32 src1 (imm $I32 (u32_as_u64 src2))))
(rule (emit_cond (Cond.IfXulteq32I32 src1 src2))
(pulley_xulteq32 src1 (imm $I32 (u32_as_u64 src2))))

;; Note the operand swaps here
(rule (emit_cond (Cond.IfXsgt32I32 src1 src2))
(pulley_xslteq32 (imm $I32 (i64_as_u64 (i32_as_i64 src2))) src1))
(rule (emit_cond (Cond.IfXsgteq32I32 src1 src2))
(pulley_xslt32 (imm $I32 (i64_as_u64 (i32_as_i64 src2))) src1))
(rule (emit_cond (Cond.IfXugt32I32 src1 src2))
(pulley_xulteq32 (imm $I32 (u32_as_u64 src2)) src1))
(rule (emit_cond (Cond.IfXugteq32I32 src1 src2))
(pulley_xult32 (imm $I32 (u32_as_u64 src2)) src1))

(rule (emit_cond (Cond.IfXeq64I32 src1 src2))
(pulley_xeq64 src1 (imm $I64 (i64_as_u64 (i32_as_i64 src2)))))
(rule (emit_cond (Cond.IfXneq64I32 src1 src2))
(pulley_xneq64 src1 (imm $I64 (i64_as_u64 (i32_as_i64 src2)))))
(rule (emit_cond (Cond.IfXslt64I32 src1 src2))
(pulley_xslt64 src1 (imm $I64 (i64_as_u64 (i32_as_i64 src2)))))
(rule (emit_cond (Cond.IfXslteq64I32 src1 src2))
(pulley_xslteq64 src1 (imm $I64 (i64_as_u64 (i32_as_i64 src2)))))
(rule (emit_cond (Cond.IfXult64I32 src1 src2))
(pulley_xult64 src1 (imm $I64 (u32_as_u64 src2))))
(rule (emit_cond (Cond.IfXulteq64I32 src1 src2))
(pulley_xulteq64 src1 (imm $I64 (u32_as_u64 src2))))

;; Note the operand swaps here
(rule (emit_cond (Cond.IfXsgt64I32 src1 src2))
(pulley_xslteq64 (imm $I64 (i64_as_u64 (i32_as_i64 src2))) src1))
(rule (emit_cond (Cond.IfXsgteq64I32 src1 src2))
(pulley_xslt64 (imm $I64 (i64_as_u64 (i32_as_i64 src2))) src1))
(rule (emit_cond (Cond.IfXugt64I32 src1 src2))
(pulley_xulteq64 (imm $I64 (u32_as_u64 src2)) src1))
(rule (emit_cond (Cond.IfXugteq64I32 src1 src2))
(pulley_xult64 (imm $I64 (u32_as_u64 src2)) src1))

;;;; Rules for `bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type $F32 (bitcast _flags val @ (value_type $I32))))
Expand Down
Loading
Loading