From d9b42188314df597558baf719218d2d0cd332905 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 25 Nov 2015 22:13:48 +0000 Subject: [PATCH] [WebAssembly] Fold setne and seteq comparisons into selects. llvm-svn: 254104 --- .../WebAssembly/WebAssemblyInstrFloat.td | 14 ++ .../WebAssembly/WebAssemblyInstrInteger.td | 14 ++ llvm/test/CodeGen/WebAssembly/select.ll | 148 ++++++++++++++---- 3 files changed, 148 insertions(+), 28 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td index a24c8bfdef36..0d819581621e 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td @@ -73,3 +73,17 @@ def SELECT_F64 : I<(outs F64:$dst), (ins I32:$cond, F64:$lhs, F64:$rhs), "f64.select\t$dst, $cond, $lhs, $rhs">; } // Defs = [ARGUMENTS] + +// ISD::SELECT requires its operand to conform to getBooleanContents, but +// WebAssembly's select interprets any non-zero value as true, so we can fold +// a setne with 0 into a select. +def : Pat<(select (i32 (setne I32:$cond, 0)), F32:$lhs, F32:$rhs), + (SELECT_F32 I32:$cond, F32:$lhs, F32:$rhs)>; +def : Pat<(select (i32 (setne I32:$cond, 0)), F64:$lhs, F64:$rhs), + (SELECT_F64 I32:$cond, F64:$lhs, F64:$rhs)>; + +// And again, this time with seteq instead of setne and the arms reversed. +def : Pat<(select (i32 (seteq I32:$cond, 0)), F32:$lhs, F32:$rhs), + (SELECT_F32 I32:$cond, F32:$rhs, F32:$lhs)>; +def : Pat<(select (i32 (seteq I32:$cond, 0)), F64:$lhs, F64:$rhs), + (SELECT_F64 I32:$cond, F64:$rhs, F64:$lhs)>; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td index bc00cd6b4f7f..3fa2f712034a 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td @@ -63,3 +63,17 @@ def SELECT_I64 : I<(outs I64:$dst), (ins I32:$cond, I64:$lhs, I64:$rhs), "i64.select\t$dst, $cond, $lhs, $rhs">; } // Defs = [ARGUMENTS] + +// ISD::SELECT requires its operand to conform to getBooleanContents, but +// WebAssembly's select interprets any non-zero value as true, so we can fold +// a setne with 0 into a select. +def : Pat<(select (i32 (setne I32:$cond, 0)), I32:$lhs, I32:$rhs), + (SELECT_I32 I32:$cond, I32:$lhs, I32:$rhs)>; +def : Pat<(select (i32 (setne I32:$cond, 0)), I64:$lhs, I64:$rhs), + (SELECT_I64 I32:$cond, I64:$lhs, I64:$rhs)>; + +// And again, this time with seteq instead of setne and the arms reversed. +def : Pat<(select (i32 (seteq I32:$cond, 0)), I32:$lhs, I32:$rhs), + (SELECT_I32 I32:$cond, I32:$rhs, I32:$lhs)>; +def : Pat<(select (i32 (seteq I32:$cond, 0)), I64:$lhs, I64:$rhs), + (SELECT_I64 I32:$cond, I64:$rhs, I64:$lhs)>; diff --git a/llvm/test/CodeGen/WebAssembly/select.ll b/llvm/test/CodeGen/WebAssembly/select.ll index eab7720b5564..1b1d7aed7154 100644 --- a/llvm/test/CodeGen/WebAssembly/select.ll +++ b/llvm/test/CodeGen/WebAssembly/select.ll @@ -6,38 +6,130 @@ target datalayout = "e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" -; CHECK-LABEL: select_i32: -; CHECK: i32.eq $push[[NUM1:[0-9]+]]=, $2, $pop[[NUM0:[0-9]+]]{{$}} -; CHECK: i32.select $push{{[0-9]+}}=, $pop[[NUM1]], $0, $1{{$}} -define i32 @select_i32(i32 %a, i32 %b, i32 %cond) { - %cc = icmp eq i32 %cond, 0 - %result = select i1 %cc, i32 %a, i32 %b - ret i32 %result +; CHECK-LABEL: select_i32_bool: +; CHECK-NEXT: .param i32, i32, i32{{$}} +; CHECK-NEXT: .result i32{{$}} +; CHECK-NEXT: i32.select $push0=, $0, $1, $2{{$}} +; CHECK-NEXT: return $pop0{{$}} +define i32 @select_i32_bool(i1 zeroext %a, i32 %b, i32 %c) { + %cond = select i1 %a, i32 %b, i32 %c + ret i32 %cond } -; CHECK-LABEL: select_i64: -; CHECK: i32.eq $push[[NUM1:[0-9]+]]=, $2, $pop[[NUM0:[0-9]+]]{{$}} -; CHECK: i64.select $push{{[0-9]+}}=, $pop[[NUM1]], $0, $1{{$}} -define i64 @select_i64(i64 %a, i64 %b, i32 %cond) { - %cc = icmp eq i32 %cond, 0 - %result = select i1 %cc, i64 %a, i64 %b - ret i64 %result +; CHECK-LABEL: select_i32_eq: +; CHECK-NEXT: .param i32, i32, i32{{$}} +; CHECK-NEXT: .result i32{{$}} +; CHECK-NEXT: i32.select $push0=, $0, $2, $1{{$}} +; CHECK-NEXT: return $pop0{{$}} +define i32 @select_i32_eq(i32 %a, i32 %b, i32 %c) { + %cmp = icmp eq i32 %a, 0 + %cond = select i1 %cmp, i32 %b, i32 %c + ret i32 %cond } -; CHECK-LABEL: select_f32: -; CHECK: i32.eq $push[[NUM1:[0-9]+]]=, $2, $pop[[NUM0:[0-9]+]]{{$}} -; CHECK: f32.select $push{{[0-9]+}}=, $pop[[NUM1]], $0, $1{{$}} -define float @select_f32(float %a, float %b, i32 %cond) { - %cc = icmp eq i32 %cond, 0 - %result = select i1 %cc, float %a, float %b - ret float %result +; CHECK-LABEL: select_i32_ne: +; CHECK-NEXT: .param i32, i32, i32{{$}} +; CHECK-NEXT: .result i32{{$}} +; CHECK-NEXT: i32.select $push0=, $0, $1, $2{{$}} +; CHECK-NEXT: return $pop0{{$}} +define i32 @select_i32_ne(i32 %a, i32 %b, i32 %c) { + %cmp = icmp ne i32 %a, 0 + %cond = select i1 %cmp, i32 %b, i32 %c + ret i32 %cond } -; CHECK-LABEL: select_f64: -; CHECK: i32.eq $push[[NUM1:[0-9]+]]=, $2, $pop[[NUM0:[0-9]+]]{{$}} -; CHECK: f64.select $push{{[0-9]+}}=, $pop[[NUM1]], $0, $1{{$}} -define double @select_f64(double %a, double %b, i32 %cond) { - %cc = icmp eq i32 %cond, 0 - %result = select i1 %cc, double %a, double %b - ret double %result +; CHECK-LABEL: select_i64_bool: +; CHECK-NEXT: .param i32, i64, i64{{$}} +; CHECK-NEXT: .result i64{{$}} +; CHECK-NEXT: i64.select $push0=, $0, $1, $2{{$}} +; CHECK-NEXT: return $pop0{{$}} +define i64 @select_i64_bool(i1 zeroext %a, i64 %b, i64 %c) { + %cond = select i1 %a, i64 %b, i64 %c + ret i64 %cond +} + +; CHECK-LABEL: select_i64_eq: +; CHECK-NEXT: .param i32, i64, i64{{$}} +; CHECK-NEXT: .result i64{{$}} +; CHECK-NEXT: i64.select $push0=, $0, $2, $1{{$}} +; CHECK-NEXT: return $pop0{{$}} +define i64 @select_i64_eq(i32 %a, i64 %b, i64 %c) { + %cmp = icmp eq i32 %a, 0 + %cond = select i1 %cmp, i64 %b, i64 %c + ret i64 %cond +} + +; CHECK-LABEL: select_i64_ne: +; CHECK-NEXT: .param i32, i64, i64{{$}} +; CHECK-NEXT: .result i64{{$}} +; CHECK-NEXT: i64.select $push0=, $0, $1, $2{{$}} +; CHECK-NEXT: return $pop0{{$}} +define i64 @select_i64_ne(i32 %a, i64 %b, i64 %c) { + %cmp = icmp ne i32 %a, 0 + %cond = select i1 %cmp, i64 %b, i64 %c + ret i64 %cond +} + +; CHECK-LABEL: select_f32_bool: +; CHECK-NEXT: .param i32, f32, f32{{$}} +; CHECK-NEXT: .result f32{{$}} +; CHECK-NEXT: f32.select $push0=, $0, $1, $2{{$}} +; CHECK-NEXT: return $pop0{{$}} +define float @select_f32_bool(i1 zeroext %a, float %b, float %c) { + %cond = select i1 %a, float %b, float %c + ret float %cond +} + +; CHECK-LABEL: select_f32_eq: +; CHECK-NEXT: .param i32, f32, f32{{$}} +; CHECK-NEXT: .result f32{{$}} +; CHECK-NEXT: f32.select $push0=, $0, $2, $1{{$}} +; CHECK-NEXT: return $pop0{{$}} +define float @select_f32_eq(i32 %a, float %b, float %c) { + %cmp = icmp eq i32 %a, 0 + %cond = select i1 %cmp, float %b, float %c + ret float %cond +} + +; CHECK-LABEL: select_f32_ne: +; CHECK-NEXT: .param i32, f32, f32{{$}} +; CHECK-NEXT: .result f32{{$}} +; CHECK-NEXT: f32.select $push0=, $0, $1, $2{{$}} +; CHECK-NEXT: return $pop0{{$}} +define float @select_f32_ne(i32 %a, float %b, float %c) { + %cmp = icmp ne i32 %a, 0 + %cond = select i1 %cmp, float %b, float %c + ret float %cond +} + +; CHECK-LABEL: select_f64_bool: +; CHECK-NEXT: .param i32, f64, f64{{$}} +; CHECK-NEXT: .result f64{{$}} +; CHECK-NEXT: f64.select $push0=, $0, $1, $2{{$}} +; CHECK-NEXT: return $pop0{{$}} +define double @select_f64_bool(i1 zeroext %a, double %b, double %c) { + %cond = select i1 %a, double %b, double %c + ret double %cond +} + +; CHECK-LABEL: select_f64_eq: +; CHECK-NEXT: .param i32, f64, f64{{$}} +; CHECK-NEXT: .result f64{{$}} +; CHECK-NEXT: f64.select $push0=, $0, $2, $1{{$}} +; CHECK-NEXT: return $pop0{{$}} +define double @select_f64_eq(i32 %a, double %b, double %c) { + %cmp = icmp eq i32 %a, 0 + %cond = select i1 %cmp, double %b, double %c + ret double %cond +} + +; CHECK-LABEL: select_f64_ne: +; CHECK-NEXT: .param i32, f64, f64{{$}} +; CHECK-NEXT: .result f64{{$}} +; CHECK-NEXT: f64.select $push0=, $0, $1, $2{{$}} +; CHECK-NEXT: return $pop0{{$}} +define double @select_f64_ne(i32 %a, double %b, double %c) { + %cmp = icmp ne i32 %a, 0 + %cond = select i1 %cmp, double %b, double %c + ret double %cond }