diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 15dc44a043957..7f0140a5e8c66 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -839,9 +839,9 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) { unsigned Reg; - if (Attrs.hasParamAttr(I, Attribute::SExt)) + if (Call->paramHasAttr(I, Attribute::SExt)) Reg = getRegForSignedValue(V); - else if (Attrs.hasParamAttr(I, Attribute::ZExt)) + else if (Call->paramHasAttr(I, Attribute::ZExt)) Reg = getRegForUnsignedValue(V); else Reg = getRegForValue(V); diff --git a/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll b/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll new file mode 100644 index 0000000000000..e33337f278060 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll @@ -0,0 +1,186 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -O0 | FileCheck %s +; RUN: llc -fast-isel=false < %s -O0 | FileCheck %s -check-prefixes NO-FAST-ISEL + +target triple = "wasm32-unknown-unknown" + + +declare i32 @foo(i1 signext noundef, i32 noundef) + +; callsite_signext and callsite_nosignext must emit equivalent codes + +define i32 @callsite_nosignext() { +; CHECK-LABEL: callsite_nosignext: +; CHECK: .functype callsite_nosignext () -> (i32) +; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32 +; CHECK-NEXT: # %bb.0: # %start +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: i32.const 31 +; CHECK-NEXT: local.set 2 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.shl +; CHECK-NEXT: local.set 3 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.shr_s +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: local.get 4 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: call foo +; CHECK-NEXT: local.set 5 +; CHECK-NEXT: local.get 5 +; CHECK-NEXT: return +; +; NO-FAST-ISEL-LABEL: callsite_nosignext: +; NO-FAST-ISEL: .functype callsite_nosignext () -> (i32) +; NO-FAST-ISEL-NEXT: .local i32, i32, i32 +; NO-FAST-ISEL-NEXT: # %bb.0: # %start +; NO-FAST-ISEL-NEXT: i32.const 0 +; NO-FAST-ISEL-NEXT: local.set 0 +; NO-FAST-ISEL-NEXT: i32.const -1 +; NO-FAST-ISEL-NEXT: local.set 1 +; NO-FAST-ISEL-NEXT: local.get 1 +; NO-FAST-ISEL-NEXT: local.get 0 +; NO-FAST-ISEL-NEXT: call foo +; NO-FAST-ISEL-NEXT: local.set 2 +; NO-FAST-ISEL-NEXT: local.get 2 +; NO-FAST-ISEL-NEXT: return +start: + %0 = call i32 @foo(i1 1, i32 0) + ret i32 %0 +} + +define i32 @callsite_signext() { +; CHECK-LABEL: callsite_signext: +; CHECK: .functype callsite_signext () -> (i32) +; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32 +; CHECK-NEXT: # %bb.0: # %start +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: i32.const 31 +; CHECK-NEXT: local.set 2 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.shl +; CHECK-NEXT: local.set 3 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.shr_s +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: local.get 4 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: call foo +; CHECK-NEXT: local.set 5 +; CHECK-NEXT: local.get 5 +; CHECK-NEXT: return +; +; NO-FAST-ISEL-LABEL: callsite_signext: +; NO-FAST-ISEL: .functype callsite_signext () -> (i32) +; NO-FAST-ISEL-NEXT: .local i32, i32, i32 +; NO-FAST-ISEL-NEXT: # %bb.0: # %start +; NO-FAST-ISEL-NEXT: i32.const 0 +; NO-FAST-ISEL-NEXT: local.set 0 +; NO-FAST-ISEL-NEXT: i32.const -1 +; NO-FAST-ISEL-NEXT: local.set 1 +; NO-FAST-ISEL-NEXT: local.get 1 +; NO-FAST-ISEL-NEXT: local.get 0 +; NO-FAST-ISEL-NEXT: call foo +; NO-FAST-ISEL-NEXT: local.set 2 +; NO-FAST-ISEL-NEXT: local.get 2 +; NO-FAST-ISEL-NEXT: return +start: + %0 = call i32 @foo(i1 signext 1, i32 0) + ret i32 %0 +} + +declare i32 @foo2(i1 zeroext noundef, i32 noundef) + +; callsite_zeroext and callsite_nozeroext must emit equivalent codes + +define i32 @callsite_nozeroext() { +; CHECK-LABEL: callsite_nozeroext: +; CHECK: .functype callsite_nozeroext () -> (i32) +; CHECK-NEXT: .local i32, i32, i32, i32, i32 +; CHECK-NEXT: # %bb.0: # %start +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 2 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.and +; CHECK-NEXT: local.set 3 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: call foo2 +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: local.get 4 +; CHECK-NEXT: return +; +; NO-FAST-ISEL-LABEL: callsite_nozeroext: +; NO-FAST-ISEL: .functype callsite_nozeroext () -> (i32) +; NO-FAST-ISEL-NEXT: .local i32, i32, i32 +; NO-FAST-ISEL-NEXT: # %bb.0: # %start +; NO-FAST-ISEL-NEXT: i32.const 0 +; NO-FAST-ISEL-NEXT: local.set 0 +; NO-FAST-ISEL-NEXT: i32.const 1 +; NO-FAST-ISEL-NEXT: local.set 1 +; NO-FAST-ISEL-NEXT: local.get 1 +; NO-FAST-ISEL-NEXT: local.get 0 +; NO-FAST-ISEL-NEXT: call foo2 +; NO-FAST-ISEL-NEXT: local.set 2 +; NO-FAST-ISEL-NEXT: local.get 2 +; NO-FAST-ISEL-NEXT: return +start: + %0 = call i32 @foo2(i1 1, i32 0) + ret i32 %0 +} + +define i32 @callsite_zeroext() { +; CHECK-LABEL: callsite_zeroext: +; CHECK: .functype callsite_zeroext () -> (i32) +; CHECK-NEXT: .local i32, i32, i32, i32, i32 +; CHECK-NEXT: # %bb.0: # %start +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 2 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.and +; CHECK-NEXT: local.set 3 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: call foo2 +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: local.get 4 +; CHECK-NEXT: return +; +; NO-FAST-ISEL-LABEL: callsite_zeroext: +; NO-FAST-ISEL: .functype callsite_zeroext () -> (i32) +; NO-FAST-ISEL-NEXT: .local i32, i32, i32 +; NO-FAST-ISEL-NEXT: # %bb.0: # %start +; NO-FAST-ISEL-NEXT: i32.const 0 +; NO-FAST-ISEL-NEXT: local.set 0 +; NO-FAST-ISEL-NEXT: i32.const 1 +; NO-FAST-ISEL-NEXT: local.set 1 +; NO-FAST-ISEL-NEXT: local.get 1 +; NO-FAST-ISEL-NEXT: local.get 0 +; NO-FAST-ISEL-NEXT: call foo2 +; NO-FAST-ISEL-NEXT: local.set 2 +; NO-FAST-ISEL-NEXT: local.get 2 +; NO-FAST-ISEL-NEXT: return +start: + %0 = call i32 @foo2(i1 zeroext 1, i32 0) + ret i32 %0 +}