Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1809,7 +1809,7 @@ // offsets to its parts don't wrap either. SDValue Ptr = DAG.getObjectPtrOffset(getCurSDLoc(), RetPtr, Offsets[i]); - SDValue Val = RetOp.getValue(i); + SDValue Val = RetOp.getValue(RetOp.getResNo() + i); if (MemVTs[i] != ValueVTs[i]) Val = DAG.getPtrExtOrTrunc(Val, getCurSDLoc(), MemVTs[i]); Chains[i] = DAG.getStore(Chain, getCurSDLoc(), Val, Index: test/CodeGen/WebAssembly/multi-return.ll =================================================================== --- test/CodeGen/WebAssembly/multi-return.ll +++ test/CodeGen/WebAssembly/multi-return.ll @@ -0,0 +1,303 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -asm-verbose=false | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +; Return multiple values, some of which will be legalized into multiple values. +declare { i64, i128, i192, i128, i64 } @return_multi_multi() + +; Test returning a single value from @return_multi_multi. + +define i64 @test0() { +; CHECK-LABEL: test0 +; CHECK: call return_multi_multi +; CHECK: local.get 0 +; CHECK: i64.load 8 +; CHECK: local.set 1 +; CHECK: local.get 1 +start: + %t0 = tail call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0 + ret i64 %t1 +} + +define i128 @test1() { +; CHECK-LABEL: test1 +; CHECK: call return_multi_multi +; CHECK: local.get 1 +; CHECK: i64.load 16 +; CHECK: local.set 2 +; CHECK: local.get 0 +; CHECK: local.get 1 +; CHECK: i32.const 24 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: i64.store 8 +; CHECK: local.get 0 +; CHECK: local.get 2 +; CHECK: i64.store 0 +start: + %t0 = tail call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1 + ret i128 %t1 +} + +define i192 @test2() { +; CHECK-LABEL: test2 +; CHECK: call return_multi_multi +; CHECK: local.get 1 +; CHECK: i32.const 40 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: local.set 2 +; CHECK: local.get 1 +; CHECK: i64.load 32 +; CHECK: local.set 3 +; CHECK: local.get 0 +; CHECK: local.get 1 +; CHECK: i32.const 48 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: i64.store 16 +; CHECK: local.get 0 +; CHECK: local.get 3 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: local.get 2 +; CHECK: i64.store 8 +start: + %t0 = tail call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2 + ret i192 %t1 +} + +define i128 @test3() { +; CHECK-LABEL: test3 +; CHECK: call return_multi_multi +; CHECK: local.get 1 +; CHECK: i64.load 56 +; CHECK: local.set 2 +; CHECK: local.get 0 +; CHECK: local.get 1 +; CHECK: i32.const 64 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: i64.store 8 +; CHECK: local.get 0 +; CHECK: local.get 2 +; CHECK: i64.store 0 +start: + %t0 = tail call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3 + ret i128 %t1 +} + +define i64 @test4() { +; CHECK-LABEL: test4 +; CHECK: call return_multi_multi +; CHECK: local.get 0 +; CHECK: i64.load 72 +; CHECK: local.set 1 +; CHECK: local.get 1 +start: + %t0 = tail call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 4 + ret i64 %t1 +} + +; Test returning multiple values from @return_multi_multi. + +define { i64, i128 } @test5() { +; CHECK-LABEL: test5 +; CHECK: call return_multi_multi +; CHECK: local.get 1 +; CHECK: i32.const 8 +; CHECK: i32.add +; CHECK: i32.const 16 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: local.set 2 +; CHECK: local.get 1 +; CHECK: i64.load 8 +; CHECK: local.set 3 +; CHECK: local.get 0 +; CHECK: local.get 1 +; CHECK: i64.load 16 +; CHECK: i64.store 8 +; CHECK: local.get 0 +; CHECK: i32.const 16 +; CHECK: i32.add +; CHECK: local.get 2 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: local.get 3 +; CHECK: i64.store 0 +start: + %t0 = tail call { i64, i128, i192, i128, i64 } @return_multi_multi() + %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0 + %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1 + %s0 = insertvalue { i64, i128 } undef, i64 %r0, 0 + %s1 = insertvalue { i64, i128 } %s0, i128 %r1, 1 + ret { i64, i128 } %s1 +} + +define { i128, i128 } @test6() { +; CHECK-LABEL: test6 +; CHECK: call return_multi_multi +; CHECK: local.get 1 +; CHECK: i32.const 24 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: local.set 2 +; CHECK: local.get 1 +; CHECK: i32.const 64 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: local.set 3 +; CHECK: local.get 1 +; CHECK: i64.load 16 +; CHECK: local.set 4 +; CHECK: local.get 0 +; CHECK: local.get 1 +; CHECK: i64.load 56 +; CHECK: i64.store 16 +; CHECK: local.get 0 +; CHECK: i32.const 24 +; CHECK: i32.add +; CHECK: local.get 3 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: local.get 4 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: local.get 2 +; CHECK: i64.store 8 +start: + %t0 = tail call { i64, i128, i192, i128, i64 } @return_multi_multi() + %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1 + %r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3 + %s0 = insertvalue { i128, i128 } undef, i128 %r1, 0 + %s1 = insertvalue { i128, i128 } %s0, i128 %r3, 1 + ret { i128, i128 } %s1 +} + +define { i64, i192 } @test7() { +; CHECK-LABEL: test7 +; CHECK: call return_multi_multi +; CHECK: local.get 1 +; CHECK: i32.const 40 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: local.set 2 +; CHECK: local.get 1 +; CHECK: i64.load 8 +; CHECK: local.set 3 +; CHECK: local.get 1 +; CHECK: i64.load 32 +; CHECK: local.set 4 +; CHECK: local.get 0 +; CHECK: i32.const 24 +; CHECK: i32.add +; CHECK: local.get 1 +; CHECK: i32.const 48 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: local.get 4 +; CHECK: i64.store 8 +; CHECK: local.get 0 +; CHECK: i32.const 16 +; CHECK: i32.add +; CHECK: local.get 2 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: local.get 3 +; CHECK: i64.store 0 +start: + %t0 = tail call { i64, i128, i192, i128, i64 } @return_multi_multi() + %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0 + %r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2 + %s0 = insertvalue { i64, i192 } undef, i64 %r0, 0 + %s1 = insertvalue { i64, i192 } %s0, i192 %r2, 1 + ret { i64, i192 } %s1 +} + +define { i128, i192, i128, i64 } @test8() { +; CHECK-LABEL: test8 +; CHECK: call return_multi_multi +; CHECK: local.get 1 +; CHECK: i32.const 64 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: local.set 2 +; CHECK: local.get 1 +; CHECK: i32.const 8 +; CHECK: i32.add +; CHECK: i32.const 32 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: local.set 3 +; CHECK: local.get 1 +; CHECK: i32.const 48 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: local.set 4 +; CHECK: local.get 1 +; CHECK: i32.const 24 +; CHECK: i32.add +; CHECK: i64.load 0 +; CHECK: local.set 5 +; CHECK: local.get 1 +; CHECK: i64.load 8 +; CHECK: local.set 6 +; CHECK: local.get 1 +; CHECK: i64.load 56 +; CHECK: local.set 7 +; CHECK: local.get 1 +; CHECK: i64.load 32 +; CHECK: local.set 8 +; CHECK: local.get 0 +; CHECK: local.get 1 +; CHECK: i64.load 16 +; CHECK: i64.store 40 +; CHECK: local.get 0 +; CHECK: i32.const 48 +; CHECK: i32.add +; CHECK: local.get 5 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: i32.const 32 +; CHECK: i32.add +; CHECK: local.get 4 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: local.get 8 +; CHECK: i64.store 16 +; CHECK: local.get 0 +; CHECK: i32.const 24 +; CHECK: i32.add +; CHECK: local.get 3 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: local.get 7 +; CHECK: i64.store 0 +; CHECK: local.get 0 +; CHECK: local.get 2 +; CHECK: i64.store 8 +; CHECK: local.get 0 +; CHECK: local.get 6 +; CHECK: i64.store 56 +start: + %t0 = tail call { i64, i128, i192, i128, i64 } @return_multi_multi() + %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0 + %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1 + %r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2 + %r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3 + %s0 = insertvalue { i128, i192, i128, i64 } undef, i128 %r3, 0 + %s1 = insertvalue { i128, i192, i128, i64 } %s0, i192 %r2, 1 + %s2 = insertvalue { i128, i192, i128, i64 } %s1, i128 %r1, 2 + %s3 = insertvalue { i128, i192, i128, i64 } %s2, i64 %r0, 3 + ret { i128, i192, i128, i64 } %s3 +}