Fix bitcode parser to check type signatures of functions.

Before, type signatures of functions were only checked when called.
This CL fixes this by checking all function signatures.

BUG=None
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1579203002 .
diff --git a/src/IceConverter.cpp b/src/IceConverter.cpp
index 0907167..e54dd2a 100644
--- a/src/IceConverter.cpp
+++ b/src/IceConverter.cpp
@@ -880,6 +880,8 @@
         StrBuf << "\n  Use flag -allow-externally-defined-symbols to override";
       report_fatal_error(StrBuf.str());
     }
+    if (!IceFunc->validateTypeSignature(Ctx))
+      report_fatal_error(IceFunc->getTypeSignatureError(Ctx));
     GlobalDeclarationMap[&Func] = IceFunc;
   }
   // Install global variable declarations.
diff --git a/src/IceGlobalInits.cpp b/src/IceGlobalInits.cpp
index ab53eac..94a38a1 100644
--- a/src/IceGlobalInits.cpp
+++ b/src/IceGlobalInits.cpp
@@ -60,6 +60,56 @@
 
 namespace Ice {
 
+const Intrinsics::FullIntrinsicInfo *
+FunctionDeclaration::getIntrinsicInfo(const GlobalContext *Ctx,
+                                      bool *IsIntrinsic) const {
+  *IsIntrinsic = false;
+  if (!hasName())
+    return nullptr;
+  bool BadIntrinsic;
+  const Intrinsics::FullIntrinsicInfo *Info =
+      Ctx->getIntrinsicsInfo().find(getName(), BadIntrinsic);
+  *IsIntrinsic = Info || BadIntrinsic;
+  return Info;
+}
+
+bool FunctionDeclaration::validateRegularTypeSignature() const {
+  for (SizeT i = 0; i < Signature.getNumArgs(); ++i) {
+    if (!isCallParameterType(Signature.getArgType(i)))
+      return false;
+  }
+  return isCallReturnType(Signature.getReturnType());
+}
+
+bool FunctionDeclaration::validateIntrinsicTypeSignature(
+    const Intrinsics::FullIntrinsicInfo *Info) const {
+  if (Signature.getNumArgs() != Info->getNumArgs())
+    return false;
+  for (SizeT i = 0; i < Signature.getNumArgs(); ++i) {
+    if (Signature.getArgType(i) != Info->getArgType(i))
+      return false;
+  }
+  return Signature.getReturnType() == Info->getReturnType();
+}
+
+IceString FunctionDeclaration::getTypeSignatureError(const GlobalContext *Ctx) {
+  std::string Buffer;
+  llvm::raw_string_ostream StrBuf(Buffer);
+  StrBuf << "Invalid";
+  bool IsIntrinsic;
+  const Intrinsics::FullIntrinsicInfo *Info =
+      getIntrinsicInfo(Ctx, &IsIntrinsic);
+  if (IsIntrinsic && Info == nullptr) {
+    StrBuf << " intrinsic name: " << getName();
+    return StrBuf.str();
+  }
+  StrBuf << " type signature for";
+  if (IsIntrinsic)
+    StrBuf << " intrinsic";
+  StrBuf << " " << getName() << ": " << getSignature();
+  return StrBuf.str();
+}
+
 void FunctionDeclaration::dumpType(Ostream &Stream) const {
   if (!Ice::BuildDefs::dump())
     return;
diff --git a/src/IceGlobalInits.h b/src/IceGlobalInits.h
index 28e8142..711a563 100644
--- a/src/IceGlobalInits.h
+++ b/src/IceGlobalInits.h
@@ -21,6 +21,7 @@
 
 #include "IceDefs.h"
 #include "IceGlobalContext.h"
+#include "IceIntrinsics.h"
 #include "IceTypes.h"
 
 #ifdef __clang__
@@ -156,6 +157,32 @@
     return verifyLinkageDefault(Ctx);
   }
 
+  /// Validates that the type signature of the function is correct. Returns true
+  /// if valid.
+  bool validateTypeSignature(const GlobalContext *Ctx) const {
+    bool IsIntrinsic;
+    if (const Intrinsics::FullIntrinsicInfo *Info =
+            getIntrinsicInfo(Ctx, &IsIntrinsic))
+      return validateIntrinsicTypeSignature(Info);
+    return !IsIntrinsic && validateRegularTypeSignature();
+  }
+
+  /// Generates an error message describing why validateTypeSignature returns
+  /// false.
+  IceString getTypeSignatureError(const GlobalContext *Ctx);
+
+  /// Returns corresponding PNaCl intrisic information.
+  const Intrinsics::FullIntrinsicInfo *
+  getIntrinsicInfo(const GlobalContext *Ctx) const {
+    bool BadIntrinsic;
+    return getIntrinsicInfo(Ctx, &BadIntrinsic);
+  }
+
+  /// Same as above, except IsIntrinsic is true if the function is intrinsic
+  /// (even if not a PNaCl intrinsic).
+  const Intrinsics::FullIntrinsicInfo *
+  getIntrinsicInfo(const GlobalContext *Ctx, bool *IsIntrinsic) const;
+
 private:
   const Ice::FuncSigType Signature;
   llvm::CallingConv::ID CallingConv;
@@ -173,12 +200,15 @@
   }
 
   bool isIntrinsicName(const GlobalContext *Ctx) const {
-    if (!hasName())
-      return false;
-    bool BadIntrinsic;
-    return Ctx->getIntrinsicsInfo().find(getName(), BadIntrinsic) &&
-           !BadIntrinsic;
+    bool IsIntrinsic;
+    getIntrinsicInfo(Ctx, &IsIntrinsic);
+    return IsIntrinsic;
   }
+
+  bool validateRegularTypeSignature() const;
+
+  bool validateIntrinsicTypeSignature(
+      const Intrinsics::FullIntrinsicInfo *Info) const;
 };
 
 /// Models a global variable declaration, and its initializers.
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index a7b367c..13e0870 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -338,6 +338,8 @@
     installFunctionNames();
   }
 
+  void verifyFunctionTypeSignatures();
+
   void createValueIDs() {
     assert(VariableDeclarations);
     ValueIDConstants.reserve(VariableDeclarations->size() +
@@ -637,6 +639,14 @@
   return Ice::IceType_void;
 }
 
+void TopLevelParser::verifyFunctionTypeSignatures() {
+  const Ice::GlobalContext *Ctx = getTranslator().getContext();
+  for (Ice::FunctionDeclaration *FuncDecl : FunctionDeclarations) {
+    if (!FuncDecl->validateTypeSignature(Ctx))
+      Error(FuncDecl->getTypeSignatureError(Ctx));
+  }
+}
+
 // Base class for parsing blocks within the bitcode file. Note: Because this is
 // the base class of block parsers, we generate error messages if ParseBlock or
 // ParseRecord is not overridden in derived classes.
@@ -2648,16 +2658,7 @@
       }
 
       // Check if this direct call is to an Intrinsic (starts with "llvm.")
-      bool BadIntrinsic;
-      IntrinsicInfo = getTranslator().getContext()->getIntrinsicsInfo().find(
-          Fcn->getName(), BadIntrinsic);
-      if (BadIntrinsic) {
-        std::string Buffer;
-        raw_string_ostream StrBuf(Buffer);
-        StrBuf << "Invalid PNaCl intrinsic call to " << Fcn->getName();
-        Error(StrBuf.str());
-        IntrinsicInfo = nullptr;
-      }
+      IntrinsicInfo = Fcn->getIntrinsicInfo(getTranslator().getContext());
       if (IntrinsicInfo && IntrinsicInfo->getNumArgs() != NumParams) {
         std::string Buffer;
         raw_string_ostream StrBuf(Buffer);
@@ -2712,16 +2713,14 @@
       if (Signature)
         verifyCallArgTypeMatches(Fcn, Index, OpType,
                                  Signature->getArgType(Index));
-      if (IntrinsicInfo) {
-        verifyCallArgTypeMatches(Fcn, Index, OpType,
-                                 IntrinsicInfo->getArgType(Index));
-      } else if (!isCallParameterType(OpType)) {
+      else if (!isCallParameterType(OpType)) {
         std::string Buffer;
         raw_string_ostream StrBuf(Buffer);
         StrBuf << "Argument " << *Op << " of " << printName(Fcn)
                << " has invalid type: " << Op->getType();
         Error(StrBuf.str());
         appendErrorInstruction(ReturnType);
+        return;
       }
     }
 
@@ -3007,6 +3006,7 @@
     if (!GlobalDeclarationNamesAndInitializersInstalled) {
       Context->installGlobalNames();
       Context->createValueIDs();
+      Context->verifyFunctionTypeSignatures();
       std::unique_ptr<Ice::VariableDeclarationList> Globals =
           Context->getGlobalVariables();
       if (Globals)
diff --git a/tests_lit/llvm2ice_tests/div_legalization.ll b/tests_lit/llvm2ice_tests/div_legalization.ll
index b4832d1..4624dcf 100644
--- a/tests_lit/llvm2ice_tests/div_legalization.ll
+++ b/tests_lit/llvm2ice_tests/div_legalization.ll
@@ -4,9 +4,10 @@
 ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 | FileCheck %s
 ; RUN: %p2i --filetype=obj --disassemble -i %s --args -Om1 | FileCheck %s
 
-define internal i32 @Sdiv_const8_b(i8 %a) {
+define internal i32 @Sdiv_const8_b(i32 %a32) {
 ; CHECK-LABEL: Sdiv_const8_b
 entry:
+  %a = trunc i32 %a32 to i8
   %div = sdiv i8 %a, 12
 ; CHECK: mov {{.*}},0xc
 ; CHECK-NOT: idiv 0xc
@@ -14,9 +15,10 @@
   ret i32 %div_ext
 }
 
-define internal i32 @Sdiv_const16_b(i16 %a) {
+define internal i32 @Sdiv_const16_b(i32 %a32) {
 ; CHECK-LABEL: Sdiv_const16_b
 entry:
+  %a = trunc i32 %a32 to i16
   %div = sdiv i16 %a, 1234
 ; CHECK: mov {{.*}},0x4d2
 ; CHECK-NOT: idiv 0x4d2
diff --git a/tests_lit/llvm2ice_tests/rmw.ll b/tests_lit/llvm2ice_tests/rmw.ll
index cd78977..39f5a32 100644
--- a/tests_lit/llvm2ice_tests/rmw.ll
+++ b/tests_lit/llvm2ice_tests/rmw.ll
@@ -40,8 +40,9 @@
 ; CHECK-LABEL: no_rmw_add_i32_var
 ; CHECK: add e{{ax|bx|cx|dx|bp|di|si}},DWORD PTR [e{{ax|bx|cx|dx|bp|di|si}}]
 
-define internal void @rmw_add_i16_var(i32 %addr_arg, i16 %var) {
+define internal void @rmw_add_i16_var(i32 %addr_arg, i32 %var32) {
 entry:
+  %var = trunc i32 %var32 to i16
   %addr = inttoptr i32 %addr_arg to i16*
   %val = load i16, i16* %addr, align 1
   %rmw = add i16 %val, %var
@@ -64,8 +65,9 @@
 ; CHECK-LABEL: rmw_add_i16_imm
 ; CHECK: add WORD PTR [e{{ax|bx|cx|dx|bp|di|si}}],0x13
 
-define internal void @rmw_add_i8_var(i32 %addr_arg, i8 %var) {
+define internal void @rmw_add_i8_var(i32 %addr_arg, i32 %var32) {
 entry:
+  %var = trunc i32 %var32 to i8
   %addr = inttoptr i32 %addr_arg to i8*
   %val = load i8, i8* %addr, align 1
   %rmw = add i8 %val, %var
diff --git a/tests_lit/parse_errs/Inputs/call-fcn-bad-param-type.tbc b/tests_lit/parse_errs/Inputs/call-fcn-bad-param-type.tbc
new file mode 100644
index 0000000..92b647f
--- /dev/null
+++ b/tests_lit/parse_errs/Inputs/call-fcn-bad-param-type.tbc
@@ -0,0 +1,32 @@
+65535,8,2;
+1,1;
+65535,17,2;
+1,5;
+2;
+7,32;
+7,8;
+21,0,0,1;
+21,0,0;
+65534;
+8,3,0,1,0;
+8,4,0,0,0;
+65535,19,2;
+5,0;
+65534;
+65535,14,2;
+1,1,84,101,115,116;
+1,0,102;
+65534;
+65535,12,2;
+1,1;
+65535,11,2;
+1,1;
+4,2;
+1,2;
+4,2;
+65534;
+2,1,1,0;
+34,0,5,2;
+10;
+65534;
+65534;
diff --git a/tests_lit/parse_errs/bad-intrinsic-arg.test b/tests_lit/parse_errs/bad-intrinsic-arg.test
index 5e3c6e9..ffbb894 100644
--- a/tests_lit/parse_errs/bad-intrinsic-arg.test
+++ b/tests_lit/parse_errs/bad-intrinsic-arg.test
@@ -8,7 +8,7 @@
 ; RUN:     -allow-externally-defined-symbols 2>&1 \
 ; RUN:   | FileCheck %s
 
-; CHECK: Argument 1 of llvm.nacl.setjmp expects i32. Found: double
+; CHECK: Invalid type signature for intrinsic llvm.nacl.setjmp: i32 (double)
 
 ; RUN: pnacl-bcfuzz -bitcode-as-text \
 ; RUN:     %p/Inputs/bad-intrinsic-arg.tbc -output - \
diff --git a/tests_lit/parse_errs/call-fcn-bad-param-type.ll b/tests_lit/parse_errs/call-fcn-bad-param-type.ll
index b7246e0..093807f 100644
--- a/tests_lit/parse_errs/call-fcn-bad-param-type.ll
+++ b/tests_lit/parse_errs/call-fcn-bad-param-type.ll
@@ -1,5 +1,5 @@
-; Test that even if a call parameter matches its declaration, it must still
-; be a legal call parameter type (unless declaration is intrinsic).
+; Test that a function parameter must be a legal parameter type (unless
+; declaration is intrinsic).
 
 ; REQUIRES: no_minimal_build
 
@@ -7,10 +7,10 @@
 ; RUN:      -allow-externally-defined-symbols | FileCheck %s
 
 declare void @f(i8);
+; CHECK: Invalid type signature for f: void (i8)
 
 define void @Test() {
 entry:
   call void @f(i8 1)
-; CHECK: Argument 1 of f has invalid type: i8
   ret void
 }
diff --git a/tests_lit/parse_errs/call-fcn-bad-param-type.test b/tests_lit/parse_errs/call-fcn-bad-param-type.test
new file mode 100644
index 0000000..d4df2fc
--- /dev/null
+++ b/tests_lit/parse_errs/call-fcn-bad-param-type.test
@@ -0,0 +1,53 @@
+; Show that we check parameter types of a function call against paramter types
+; of called function.
+
+; REQUIRES: no_minimal_build
+
+; RUN: not %pnacl_sz -bitcode-as-text %p/Inputs/call-fcn-bad-param-type.tbc \
+; RUN:     -bitcode-format=pnacl -notranslate -build-on-read \
+; RUN:     -allow-externally-defined-symbols 2>&1 \
+; RUN:   | FileCheck %s
+
+; RUN: pnacl-bcfuzz -bitcode-as-text -output - \
+; RUN:   %p/Inputs/call-fcn-bad-param-type.tbc \
+; RUN:   | not pnacl-bcdis -no-records | FileCheck %s --check-prefix=DIS
+
+; DIS:      module {  // BlockID = 8
+; DIS-NEXT:   version 1;
+; DIS-NEXT:   types {  // BlockID = 17
+; DIS-NEXT:     count 5;
+; DIS-NEXT:     @t0 = void;
+; DIS-NEXT:     @t1 = i32;
+; DIS-NEXT:     @t2 = i8;
+; DIS-NEXT:     @t3 = void (i32);
+; DIS-NEXT:     @t4 = void ();
+; DIS-NEXT:   }
+; DIS-NEXT:   declare external void @f0(i32);
+; DIS-NEXT:   define external void @f1();
+; DIS-NEXT:   globals {  // BlockID = 19
+; DIS-NEXT:     count 0;
+; DIS-NEXT:   }
+; DIS-NEXT:   valuesymtab {  // BlockID = 14
+; DIS-NEXT:     @f1 : "Test";
+; DIS-NEXT:     @f0 : "f";
+; DIS-NEXT:   }
+; DIS-NEXT:   function void @f1() {  // BlockID = 12
+; DIS-NEXT:     blocks 1;
+; DIS-NEXT:     constants {  // BlockID = 11
+; DIS-NEXT:       i32:
+; DIS-NEXT:         %c0 = i32 1;
+; DIS-NEXT:       i8:
+; DIS-NEXT:         %c1 = i8 1;
+; DIS-NEXT:       }
+; DIS-NEXT:   %b0:
+; DIS-NEXT:     %v0 = add i8 %c1, %c1;
+; DIS-NEXT:     call void @f0(i8 %c1);
+; DIS-NEXT: Error({{.*}}): Parameter 1 mismatch: i8 and i32
+; CHECK: Argument 1 of f expects i32. Found: i8
+; DIS-NEXT:     ret void;
+; DIS-NEXT:   }
+; DIS-NEXT: }
+
+
+
+
diff --git a/tests_lit/parse_errs/call-fcn-bad-return-type.ll b/tests_lit/parse_errs/call-fcn-bad-return-type.ll
index 873e05c..73a7c16 100644
--- a/tests_lit/parse_errs/call-fcn-bad-return-type.ll
+++ b/tests_lit/parse_errs/call-fcn-bad-return-type.ll
@@ -6,12 +6,15 @@
 ; RUN: %p2i --expect-fail -i %s --insts --args \
 ; RUN:      -allow-externally-defined-symbols | FileCheck %s
 
-declare i1 @f();
+declare i32 @f();
 
-define void @Test() {
+declare i64 @g();
+
+define void @Test(i32 %ifcn) {
 entry:
-  %v = call i1 @f()
-; CHECK: Return type of f is invalid: i1
+  %fcn =  inttoptr i32 %ifcn to i1()*
+  %v = call i1 %fcn()
+; CHECK: Return type of function is invalid: i1
   ret void
 }
 
diff --git a/tests_lit/parse_errs/fcn-bad-param-type.ll b/tests_lit/parse_errs/fcn-bad-param-type.ll
new file mode 100644
index 0000000..a4faab2
--- /dev/null
+++ b/tests_lit/parse_errs/fcn-bad-param-type.ll
@@ -0,0 +1,16 @@
+; Test that even if a call parameter matches its declaration, it must still
+; be a legal call parameter type (unless declaration is intrinsic).
+
+; REQUIRES: no_minimal_build
+
+; RUN: %p2i --expect-fail -i %s --insts --args \
+; RUN:      -allow-externally-defined-symbols | FileCheck %s
+
+declare void @f(i8);
+; CHECK: Invalid type signature for f: void (i8)
+
+define void @Test() {
+entry:
+  call void @f(i8 1)
+  ret void
+}
diff --git a/tests_lit/parse_errs/nacl-fake-intrinsic.ll b/tests_lit/parse_errs/nacl-fake-intrinsic.ll
index cef88d7..f1e066c 100644
--- a/tests_lit/parse_errs/nacl-fake-intrinsic.ll
+++ b/tests_lit/parse_errs/nacl-fake-intrinsic.ll
@@ -1,34 +1,11 @@
 ; Tests that we don't get fooled by a fake NaCl intrinsic.
 
-; TODO(kschimpf) Find way to run this through p2i. Note: Can't do this
-;                currently because run-pnacl-sz.py raises exception on error,
-;                and output is lost.
-; RUN: %if --need=allow_dump --command llvm-as < %s \
-; RUN:   | %if --need=allow_dump --command pnacl-freeze \
-; RUN        -allow-local-symbol-tables \
-; RUN:   | %if --need=allow_dump --command not %pnacl_sz -notranslate \
-; RUN:       -verbose=inst -build-on-read \
-; RUN:       -allow-pnacl-reader-error-recovery \
-; RUN:       -allow-local-symbol-tables \
-; RUN:       -filetype=obj -o /dev/null \
-; RUN:   | %if --need=allow_dump --command FileCheck %s
+; REQUIRES: allow_dump
 
-; RUN: %if --need=no_dump --command llvm-as < %s \
-; RUN:   | %if --need=no_dump --command pnacl-freeze \
-; RUN        -allow-local-symbol-tables \
-; RUN:   | %if --need=no_dump --command not %pnacl_sz -notranslate \
-; RUN:       -verbose=inst -build-on-read \
-; RUN:       -allow-pnacl-reader-error-recovery \
-; RUN:       -allow-local-symbol-tables \
-; RUN:       -filetype=obj -o /dev/null \
-; RUN:   | %if --need=no_dump --command FileCheck %s --check-prefix=MIN
+; RUN: %p2i --expect-fail -i %s --insts --args \
+; RUN:      -verbose=inst -allow-externally-defined-symbols \
+; RUN:   | FileCheck %s
 
 declare i32 @llvm.fake.i32(i32)
 
-define i32 @testFake(i32 %v) {
-  %r = call i32 @llvm.fake.i32(i32 %v)
-  ret i32 %r
-}
-
-; CHECK: Error({{.*}}): Invalid PNaCl intrinsic call to llvm.fake.i32
-; MIN: Error({{.*}}): Invalid function record: <34 0 3 1>
+; CHECK: Error({{.*}}): Invalid intrinsic name: llvm.fake.i32
diff --git a/tests_lit/reader_tests/compare.ll b/tests_lit/reader_tests/compare.ll
index 7acc3b0..bb2229b 100644
--- a/tests_lit/reader_tests/compare.ll
+++ b/tests_lit/reader_tests/compare.ll
@@ -4,7 +4,7 @@
 ; RUN:   %p2i -i %s --args -notranslate -timing | \
 ; RUN:   FileCheck --check-prefix=NOIR %s
 
-define internal i1 @IcmpI1(i32 %p1, i32 %p2) {
+define internal void @IcmpI1(i32 %p1, i32 %p2) {
 entry:
   %a1 = trunc i32 %p1 to i1
   %a2 = trunc i32 %p2 to i1
@@ -18,10 +18,10 @@
   %vsge = icmp sge i1 %a1, %a2
   %vslt = icmp slt i1 %a1, %a2
   %vsle = icmp sle i1 %a1, %a2
-  ret i1 %veq
+  ret void
 }
 
-; CHECK:      define internal i1 @IcmpI1(i32 %p1, i32 %p2) {
+; CHECK:      define internal void @IcmpI1(i32 %p1, i32 %p2) {
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:   %a1 = trunc i32 %p1 to i1
 ; CHECK-NEXT:   %a2 = trunc i32 %p2 to i1
@@ -35,10 +35,10 @@
 ; CHECK-NEXT:   %vsge = icmp sge i1 %a1, %a2
 ; CHECK-NEXT:   %vslt = icmp slt i1 %a1, %a2
 ; CHECK-NEXT:   %vsle = icmp sle i1 %a1, %a2
-; CHECK-NEXT:   ret i1 %veq
+; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
-define internal i1 @IcmpI8(i32 %p1, i32 %p2) {
+define internal void @IcmpI8(i32 %p1, i32 %p2) {
 entry:
   %a1 = trunc i32 %p1 to i8
   %a2 = trunc i32 %p2 to i8
@@ -52,10 +52,10 @@
   %vsge = icmp sge i8 %a1, %a2
   %vslt = icmp slt i8 %a1, %a2
   %vsle = icmp sle i8 %a1, %a2
-  ret i1 %veq
+  ret void
 }
 
-; CHECK-NEXT: define internal i1 @IcmpI8(i32 %p1, i32 %p2) {
+; CHECK-NEXT: define internal void @IcmpI8(i32 %p1, i32 %p2) {
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:   %a1 = trunc i32 %p1 to i8
 ; CHECK-NEXT:   %a2 = trunc i32 %p2 to i8
@@ -69,10 +69,10 @@
 ; CHECK-NEXT:   %vsge = icmp sge i8 %a1, %a2
 ; CHECK-NEXT:   %vslt = icmp slt i8 %a1, %a2
 ; CHECK-NEXT:   %vsle = icmp sle i8 %a1, %a2
-; CHECK-NEXT:   ret i1 %veq
+; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
-define internal i1 @IcmpI16(i32 %p1, i32 %p2) {
+define internal void @IcmpI16(i32 %p1, i32 %p2) {
 entry:
   %a1 = trunc i32 %p1 to i16
   %a2 = trunc i32 %p2 to i16
@@ -86,10 +86,10 @@
   %vsge = icmp sge i16 %a1, %a2
   %vslt = icmp slt i16 %a1, %a2
   %vsle = icmp sle i16 %a1, %a2
-  ret i1 %veq
+  ret void
 }
 
-; CHECK-NEXT: define internal i1 @IcmpI16(i32 %p1, i32 %p2) {
+; CHECK-NEXT: define internal void @IcmpI16(i32 %p1, i32 %p2) {
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:   %a1 = trunc i32 %p1 to i16
 ; CHECK-NEXT:   %a2 = trunc i32 %p2 to i16
@@ -103,10 +103,10 @@
 ; CHECK-NEXT:   %vsge = icmp sge i16 %a1, %a2
 ; CHECK-NEXT:   %vslt = icmp slt i16 %a1, %a2
 ; CHECK-NEXT:   %vsle = icmp sle i16 %a1, %a2
-; CHECK-NEXT:   ret i1 %veq
+; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
-define internal i1 @IcmpI32(i32 %a1, i32 %a2) {
+define internal void @IcmpI32(i32 %a1, i32 %a2) {
 entry:
   %veq = icmp eq i32 %a1, %a2
   %vne = icmp ne i32 %a1, %a2
@@ -118,10 +118,10 @@
   %vsge = icmp sge i32 %a1, %a2
   %vslt = icmp slt i32 %a1, %a2
   %vsle = icmp sle i32 %a1, %a2
-  ret i1 %veq
+  ret void
 }
 
-; CHECK-NEXT: define internal i1 @IcmpI32(i32 %a1, i32 %a2) {
+; CHECK-NEXT: define internal void @IcmpI32(i32 %a1, i32 %a2) {
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:   %veq = icmp eq i32 %a1, %a2
 ; CHECK-NEXT:   %vne = icmp ne i32 %a1, %a2
@@ -133,10 +133,10 @@
 ; CHECK-NEXT:   %vsge = icmp sge i32 %a1, %a2
 ; CHECK-NEXT:   %vslt = icmp slt i32 %a1, %a2
 ; CHECK-NEXT:   %vsle = icmp sle i32 %a1, %a2
-; CHECK-NEXT:   ret i1 %veq
+; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
-define internal i1 @IcmpI64(i64 %a1, i64 %a2) {
+define internal void @IcmpI64(i64 %a1, i64 %a2) {
 entry:
   %veq = icmp eq i64 %a1, %a2
   %vne = icmp ne i64 %a1, %a2
@@ -148,10 +148,10 @@
   %vsge = icmp sge i64 %a1, %a2
   %vslt = icmp slt i64 %a1, %a2
   %vsle = icmp sle i64 %a1, %a2
-  ret i1 %veq
+  ret void
 }
 
-; CHECK-NEXT: define internal i1 @IcmpI64(i64 %a1, i64 %a2) {
+; CHECK-NEXT: define internal void @IcmpI64(i64 %a1, i64 %a2) {
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:   %veq = icmp eq i64 %a1, %a2
 ; CHECK-NEXT:   %vne = icmp ne i64 %a1, %a2
@@ -163,7 +163,7 @@
 ; CHECK-NEXT:   %vsge = icmp sge i64 %a1, %a2
 ; CHECK-NEXT:   %vslt = icmp slt i64 %a1, %a2
 ; CHECK-NEXT:   %vsle = icmp sle i64 %a1, %a2
-; CHECK-NEXT:   ret i1 %veq
+; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
 define internal <4 x i1> @IcmpV4xI1(<4 x i1> %a1, <4 x i1> %a2) {
@@ -346,7 +346,7 @@
 ; CHECK-NEXT:   ret <4 x i1> %veq
 ; CHECK-NEXT: }
 
-define internal i1 @FcmpFloat(float %a1, float %a2) {
+define internal void @FcmpFloat(float %a1, float %a2) {
 entry:
   %vfalse = fcmp false float %a1, %a2
   %voeq = fcmp oeq float %a1, %a2
@@ -364,10 +364,10 @@
   %vune = fcmp une float %a1, %a2
   %vuno = fcmp uno float %a1, %a2
   %vtrue = fcmp true float %a1, %a2
-  ret i1 %voeq
+  ret void
 }
 
-; CHECK-NEXT: define internal i1 @FcmpFloat(float %a1, float %a2) {
+; CHECK-NEXT: define internal void @FcmpFloat(float %a1, float %a2) {
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:   %vfalse = fcmp false float %a1, %a2
 ; CHECK-NEXT:   %voeq = fcmp oeq float %a1, %a2
@@ -385,10 +385,10 @@
 ; CHECK-NEXT:   %vune = fcmp une float %a1, %a2
 ; CHECK-NEXT:   %vuno = fcmp uno float %a1, %a2
 ; CHECK-NEXT:   %vtrue = fcmp true float %a1, %a2
-; CHECK-NEXT:   ret i1 %voeq
+; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
-define internal i1 @FcmpDouble(double %a1, double %a2) {
+define internal void @FcmpDouble(double %a1, double %a2) {
 entry:
   %vfalse = fcmp false double %a1, %a2
   %voeq = fcmp oeq double %a1, %a2
@@ -406,10 +406,10 @@
   %vune = fcmp une double %a1, %a2
   %vuno = fcmp uno double %a1, %a2
   %vtrue = fcmp true double %a1, %a2
-  ret i1 %voeq
+  ret void
 }
 
-; CHECK-NEXT: define internal i1 @FcmpDouble(double %a1, double %a2) {
+; CHECK-NEXT: define internal void @FcmpDouble(double %a1, double %a2) {
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:   %vfalse = fcmp false double %a1, %a2
 ; CHECK-NEXT:   %voeq = fcmp oeq double %a1, %a2
@@ -427,7 +427,7 @@
 ; CHECK-NEXT:   %vune = fcmp une double %a1, %a2
 ; CHECK-NEXT:   %vuno = fcmp uno double %a1, %a2
 ; CHECK-NEXT:   %vtrue = fcmp true double %a1, %a2
-; CHECK-NEXT:   ret i1 %voeq
+; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
 define internal <4 x i1> @FcmpV4xFloat(<4 x float> %a1, <4 x float> %a2) {