about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorRichard Trembecký <richardt@centrum.sk>2016-04-29 22:33:41 +0200
committerCristian Cadar <c.cadar@imperial.ac.uk>2018-05-24 14:08:27 +0100
commita0cd85b41f02ce5c476612eec182aa1ff3e6fe2b (patch)
treeb7d938116cae4f4a18225e9aef2f8934b761e063
parent870f2d6aac35457e7524078a4b4a8b011f84c45c (diff)
downloadklee-a0cd85b41f02ce5c476612eec182aa1ff3e6fe2b.tar.gz
test: add versions of some tests for LLVM 3.7
Clone some tests to have their 3.7 version. 'call's, 'load's and
'getelementptr's match the new specification in them.

@andreamattavelli: Fixed test cases: BitCastAlias test cases included
modification to alias specifications that require LLVM 3.8

[v2] added comments what was changed and why
[v3] the new tests are without suffix, the old ones have ".leq36".

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
-rw-r--r--test/Concrete/BoolReadWrite.leq36.ll16
-rw-r--r--test/Concrete/BoolReadWrite.ll4
-rw-r--r--test/Concrete/ConstantExpr.leq36.ll166
-rw-r--r--test/Concrete/ConstantExpr.ll4
-rw-r--r--test/Concrete/ConstantInit.leq36.ll60
-rw-r--r--test/Concrete/ConstantInit.ll29
-rw-r--r--test/Concrete/FloatingPointOps.leq36.ll678
-rw-r--r--test/Concrete/FloatingPointOps.ll180
-rwxr-xr-xtest/Concrete/GlobalInitializers.leq36.ll48
-rwxr-xr-xtest/Concrete/GlobalInitializers.ll35
-rw-r--r--test/Concrete/SimpleStoreAndLoad.leq36.ll20
-rw-r--r--test/Concrete/SimpleStoreAndLoad.ll7
-rw-r--r--test/Feature/BitcastAlias.leq36.ll35
-rw-r--r--test/Feature/BitcastAlias.ll9
-rw-r--r--test/Feature/BitcastAliasMD2U.leq36.ll35
-rw-r--r--test/Feature/BitcastAliasMD2U.ll9
-rw-r--r--test/Feature/ConstantArray.leq36.ll52
-rw-r--r--test/Feature/ConstantArray.ll32
-rw-r--r--test/Feature/ConstantStruct.leq36.ll34
-rw-r--r--test/Feature/ConstantStruct.ll6
-rw-r--r--test/Feature/GetElementPtr.leq36.ll30
-rw-r--r--test/Feature/GetElementPtr.ll10
-rw-r--r--test/Feature/InsertExtractValue.leq36.ll34
-rw-r--r--test/Feature/InsertExtractValue.ll6
-rw-r--r--test/Feature/Overflow.leq36.ll45
-rw-r--r--test/Feature/Overflow.ll6
-rw-r--r--test/Feature/OverflowMul.leq36.ll45
-rw-r--r--test/Feature/OverflowMul.ll6
-rw-r--r--test/Feature/_utils._ll39
-rw-r--r--test/Feature/_utils.leq36._ll71
-rw-r--r--test/Intrinsics/objectsize.leq36.ll33
-rw-r--r--test/Intrinsics/objectsize.ll9
-rw-r--r--test/lit.cfg2
-rw-r--r--test/regression/2007-08-16-invalid-constant-value.c5
-rw-r--r--test/regression/2007-08-16-invalid-constant-value.leq36.c33
35 files changed, 1657 insertions, 176 deletions
diff --git a/test/Concrete/BoolReadWrite.leq36.ll b/test/Concrete/BoolReadWrite.leq36.ll
new file mode 100644
index 00000000..34a50447
--- /dev/null
+++ b/test/Concrete/BoolReadWrite.leq36.ll
@@ -0,0 +1,16 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
+
+declare void @print_i1(i1)
+
+define i32 @main() {
+        %mem = alloca i1
+        store i1 1, i1* %mem
+        %v = load i1* %mem
+        br i1 %v, label %ok, label %exit
+ok:
+	call void @print_i1(i1 %v)
+        br label %exit
+exit:
+	ret i32 0
+}
diff --git a/test/Concrete/BoolReadWrite.ll b/test/Concrete/BoolReadWrite.ll
index f818ecaf..4dfb49e0 100644
--- a/test/Concrete/BoolReadWrite.ll
+++ b/test/Concrete/BoolReadWrite.ll
@@ -1,3 +1,5 @@
+; LLVM 3.7 requires a type as the first argument to 'load'
+; REQUIRES: geq-llvm-3.7
 ; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
 
 declare void @print_i1(i1)
@@ -5,7 +7,7 @@ declare void @print_i1(i1)
 define i32 @main() {
         %mem = alloca i1
         store i1 1, i1* %mem
-        %v = load i1* %mem
+        %v = load i1, i1* %mem
         br i1 %v, label %ok, label %exit
 ok:
 	call void @print_i1(i1 %v)
diff --git a/test/Concrete/ConstantExpr.leq36.ll b/test/Concrete/ConstantExpr.leq36.ll
new file mode 100644
index 00000000..2d8e5bc6
--- /dev/null
+++ b/test/Concrete/ConstantExpr.leq36.ll
@@ -0,0 +1,166 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
+
+; Most of the test below use the *address* of gInt as part of their computation,
+; and then perform some operation (like x | ~x) which makes the result
+; deterministic. They do, however, assume that the sign bit of the address as a
+; 64-bit value will never be set.
+@gInt = global i32 10
+@gIntWithConstant = global i32 sub(i32 ptrtoint(i32* @gInt to i32), 
+                                 i32 ptrtoint(i32* @gInt to i32))
+
+define void @"test_int_to_ptr"() {
+  %t1 = add i8 ptrtoint(i8* inttoptr(i32 100 to i8*) to i8), 0
+  %t2 = add i32 ptrtoint(i32* inttoptr(i8 100 to i32*) to i32), 0
+  %t3 = add i32 ptrtoint(i32* inttoptr(i64 100 to i32*) to i32), 0
+  %t4 = add i64 ptrtoint(i8* inttoptr(i32 100 to i8*) to i64), 0
+
+  call void @print_i8(i8 %t1)
+  call void @print_i32(i32 %t2)
+  call void @print_i32(i32 %t3)
+  call void @print_i64(i64 %t4)
+    
+  ret void
+}
+
+define void @"test_constant_ops"() {
+  %t1 = add i8 trunc(i64 add(i64 ptrtoint(i32* @gInt to i64), i64 -10) to i8), 10
+  %t2 = and i64 sub(i64 sext(i32 ptrtoint(i32* @gInt to i32) to i64), i64 ptrtoint(i32* @gInt to i64)), 4294967295
+  %t3 = and i64 sub(i64 zext(i32 ptrtoint(i32* @gInt to i32) to i64), i64 ptrtoint(i32* @gInt to i64)), 4294967295
+
+  %t4 = icmp eq i8 trunc(i64 ptrtoint(i32* @gInt to i64) to i8), %t1
+  %t5 = zext i1 %t4 to i8
+    
+  call void @print_i8(i8 %t5)
+  call void @print_i64(i64 %t2)
+  call void @print_i64(i64 %t3)
+  
+  ret void
+}
+
+define void @"test_logical_ops"() {
+  %t1 = add i32 -10, and(i32 ptrtoint(i32* @gInt to i32), i32 xor(i32 ptrtoint(i32* @gInt to i32), i32 -1))
+  %t2 = add i32 -10, or(i32 ptrtoint(i32* @gInt to i32), i32 xor(i32 ptrtoint(i32* @gInt to i32), i32 -1))
+  %t3 = add i32 -10, xor(i32 xor(i32 ptrtoint(i32* @gInt to i32), i32 1024),  i32 ptrtoint(i32* @gInt to i32))
+
+  call void @print_i32(i32 %t1)
+  call void @print_i32(i32 %t2)
+  call void @print_i32(i32 %t3)
+
+  ; or the address with 1 to ensure the addresses will differ in 'ne' below
+  %t4 = shl i64 lshr(i64 or(i64 ptrtoint(i32* @gInt to i64), i64 1), i64 8), 8
+  %t5 = shl i64 ashr(i64 or(i64 ptrtoint(i32* @gInt to i64), i64 1), i64 8), 8
+  %t6 = lshr i64 shl(i64 or(i64 ptrtoint(i32* @gInt to i64), i64 1), i64 8), 8
+  
+  %t7 = icmp eq i64 %t4, %t5
+  %t8 = icmp ne i64 %t4, %t6
+  
+  %t9 = zext i1 %t7 to i8
+  %t10 = zext i1 %t8 to i8
+  
+  call void @print_i8(i8 %t9)
+  call void @print_i8(i8 %t10)
+  
+  ret void   
+}
+
+%test.struct.type = type { i32, i32 }
+@test_struct = global %test.struct.type { i32 0, i32 10 }
+
+define void @"test_misc"() {
+  ; probability that @gInt == 100 is very very low 
+  %t1 = add i32 select(i1 icmp eq (i32* @gInt, i32* inttoptr(i32 100 to i32*)), i32 10, i32 0), 0
+  call void @print_i32(i32 %t1)
+
+  %t2 = load i32* getelementptr(%test.struct.type* @test_struct, i32 0, i32 1)
+  call void @print_i32(i32 %t2)                             
+        
+  ret void
+}
+
+define void @"test_simple_arith"() {
+  %t1 = add i32 add(i32 ptrtoint(i32* @gInt to i32), i32 0), 0
+  %t2 = add i32 sub(i32 0, i32 ptrtoint(i32* @gInt to i32)), %t1
+  %t3 = mul i32 mul(i32 ptrtoint(i32* @gInt to i32), i32 10), %t2
+
+  call void @print_i32(i32 %t3)
+
+  ret void     
+}
+
+define void @"test_div_and_mod"() {
+  %t1 = add i32 udiv(i32 ptrtoint(i32* @gInt to i32), i32 13), 0
+  %t2 = add i32 urem(i32 ptrtoint(i32* @gInt to i32), i32 13), 0
+  %t3 = add i32 sdiv(i32 ptrtoint(i32* @gInt to i32), i32 13), 0
+  %t4 = add i32 srem(i32 ptrtoint(i32* @gInt to i32), i32 13), 0
+
+  %p = ptrtoint i32* @gInt to i32
+
+  %i1 = udiv i32 %p, 13
+  %i2 = urem i32 %p, 13
+  %i3 = sdiv i32 %p, 13
+  %i4 = srem i32 %p, 13
+
+  %x1 = sub i32 %t1, %i1
+  %x2 = sub i32 %t2, %i2
+  %x3 = sub i32 %t3, %i3
+  %x4 = sub i32 %t4, %i4
+
+  call void @print_i32(i32 %x1)
+  call void @print_i32(i32 %x2)
+  call void @print_i32(i32 %x3)
+  call void @print_i32(i32 %x4)
+
+  ret void     
+}
+        
+define void @test_cmp() {
+  %t1 = add i8 zext(i1 icmp ult (i64 ptrtoint(i32* @gInt to i64), i64 0) to i8), 1
+  %t2 = add i8 zext(i1 icmp ule (i64 ptrtoint(i32* @gInt to i64), i64 0) to i8), 1
+  %t3 = add i8 zext(i1 icmp uge (i64 ptrtoint(i32* @gInt to i64), i64 0) to i8), 1
+  %t4 = add i8 zext(i1 icmp ugt (i64 ptrtoint(i32* @gInt to i64), i64 0) to i8), 1
+  %t5 = add i8 zext(i1 icmp slt (i64 ptrtoint(i32* @gInt to i64), i64 0) to i8), 1
+  %t6 = add i8 zext(i1 icmp sle (i64 ptrtoint(i32* @gInt to i64), i64 0) to i8), 1
+  %t7 = add i8 zext(i1 icmp sge (i64 ptrtoint(i32* @gInt to i64), i64 0) to i8), 1
+  %t8 = add i8 zext(i1 icmp sgt (i64 ptrtoint(i32* @gInt to i64), i64 0) to i8), 1
+  %t9 = add i8 zext(i1 icmp eq (i64 ptrtoint(i32* @gInt to i64), i64 10) to i8), 1
+  %t10 = add i8 zext(i1 icmp ne (i64 ptrtoint(i32* @gInt to i64), i64 10) to i8), 1
+
+  call void @print_i1(i8 %t1)
+  call void @print_i1(i8 %t2)
+  call void @print_i1(i8 %t3)
+  call void @print_i1(i8 %t4)
+  call void @print_i1(i8 %t5)
+  call void @print_i1(i8 %t6)
+  call void @print_i1(i8 %t7)
+  call void @print_i1(i8 %t8)
+  call void @print_i1(i8 %t9)
+  call void @print_i1(i8 %t10)
+
+  ret void
+}
+
+define i32 @main() {
+    call void @test_simple_arith()
+
+    call void @test_div_and_mod()
+
+    call void @test_cmp()
+ 
+    call void @test_int_to_ptr()
+
+    call void @test_constant_ops()
+
+    call void @test_logical_ops()
+
+    call void @test_misc()
+    
+    ret i32 0
+}
+
+; defined in print_int.c
+declare void @print_i1(i8)
+declare void @print_i8(i8)
+declare void @print_i16(i16)
+declare void @print_i32(i32)
+declare void @print_i64(i64)
diff --git a/test/Concrete/ConstantExpr.ll b/test/Concrete/ConstantExpr.ll
index d00c59a6..38577f70 100644
--- a/test/Concrete/ConstantExpr.ll
+++ b/test/Concrete/ConstantExpr.ll
@@ -1,3 +1,5 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; REQUIRES: geq-llvm-3.7
 ; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
 
 ; Most of the test below use the *address* of gInt as part of their computation,
@@ -71,7 +73,7 @@ define void @"test_misc"() {
   %t1 = add i32 select(i1 icmp eq (i32* @gInt, i32* inttoptr(i32 100 to i32*)), i32 10, i32 0), 0
   call void @print_i32(i32 %t1)
 
-  %t2 = load i32* getelementptr(%test.struct.type* @test_struct, i32 0, i32 1)
+  %t2 = load i32, i32* getelementptr(%test.struct.type, %test.struct.type* @test_struct, i32 0, i32 1)
   call void @print_i32(i32 %t2)                             
         
   ret void
diff --git a/test/Concrete/ConstantInit.leq36.ll b/test/Concrete/ConstantInit.leq36.ll
new file mode 100644
index 00000000..44f85212
--- /dev/null
+++ b/test/Concrete/ConstantInit.leq36.ll
@@ -0,0 +1,60 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
+
+%struct.dirent = type { i64, i64, i16, i8 }
+declare void @print_i64(i64)
+
+define void @test_constant_vector_simple() {
+  entry:
+	%a = alloca %struct.dirent
+	%tmp1 = getelementptr %struct.dirent* %a, i32 0
+	%tmp2 = bitcast %struct.dirent* %tmp1 to <2 x i64>*
+	; Initialize with constant vector parsed as ConstantDataSequential
+	store <2 x i64> <i64 0, i64 4096>, <2 x i64>* %tmp2, align 8
+	
+	br label %exit
+exit:
+	; Print first initialized element
+	%idx = getelementptr %struct.dirent* %a, i32 0, i32 0
+	%val = load i64* %idx	
+	call void @print_i64(i64 %val)
+
+	; Print second initialized element	
+	%idx2 = getelementptr %struct.dirent* %a, i32 0, i32 1
+	%val2 = load i64* %idx2	
+	call void @print_i64(i64 %val2)
+	ret void	
+}
+
+define void @test_constant_vector_complex() {
+entry:
+    ; Create a vector using an uncommon type: i1024: Force usage of constant vector
+	%a = alloca <2 x i1024>
+	store <2 x i1024> <i1024 5, i1024 1024>, <2 x i1024>* %a, align 8
+
+	br label %exit
+exit:
+	; Print first initialized element
+	%idx = getelementptr <2 x i1024>* %a, i32 0, i32 0
+	%narrow = bitcast i1024* %idx to i64*
+	%val = load i64* %narrow
+	call void @print_i64(i64 %val)
+
+	; Print second initialized element
+	%idx2 = getelementptr <2 x i1024>* %a, i32 0, i32 1
+	%narrow2 = bitcast i1024* %idx2 to i64*
+	%val2 = load i64* %narrow2
+	call void @print_i64(i64 %val2)
+
+	ret void	
+}
+
+define i32 @main() {
+entry:
+	call void @test_constant_vector_simple()
+	call void @test_constant_vector_complex()
+
+	br label %exit
+exit:
+	ret i32 0
+}
diff --git a/test/Concrete/ConstantInit.ll b/test/Concrete/ConstantInit.ll
index 2127d27b..c30b7f09 100644
--- a/test/Concrete/ConstantInit.ll
+++ b/test/Concrete/ConstantInit.ll
@@ -1,3 +1,6 @@
+; LLVM 3.7 requires a type as the first argument to 'load'
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; REQUIRES: geq-llvm-3.7
 ; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
 
 %struct.dirent = type { i64, i64, i16, i8 }
@@ -6,23 +9,23 @@ declare void @print_i64(i64)
 define void @test_constant_vector_simple() {
   entry:
 	%a = alloca %struct.dirent
-	%tmp1 = getelementptr %struct.dirent* %a, i32 0
+	%tmp1 = getelementptr %struct.dirent, %struct.dirent* %a, i32 0
 	%tmp2 = bitcast %struct.dirent* %tmp1 to <2 x i64>*
 	; Initialize with constant vector parsed as ConstantDataSequential
 	store <2 x i64> <i64 0, i64 4096>, <2 x i64>* %tmp2, align 8
-	
+
 	br label %exit
 exit:
 	; Print first initialized element
-	%idx = getelementptr %struct.dirent* %a, i32 0, i32 0
-	%val = load i64* %idx	
+	%idx = getelementptr %struct.dirent, %struct.dirent* %a, i32 0, i32 0
+	%val = load i64, i64* %idx
 	call void @print_i64(i64 %val)
 
-	; Print second initialized element	
-	%idx2 = getelementptr %struct.dirent* %a, i32 0, i32 1
-	%val2 = load i64* %idx2	
+	; Print second initialized element
+	%idx2 = getelementptr %struct.dirent, %struct.dirent* %a, i32 0, i32 1
+	%val2 = load i64, i64* %idx2
 	call void @print_i64(i64 %val2)
-	ret void	
+	ret void
 }
 
 define void @test_constant_vector_complex() {
@@ -34,18 +37,18 @@ entry:
 	br label %exit
 exit:
 	; Print first initialized element
-	%idx = getelementptr <2 x i1024>* %a, i32 0, i32 0
+	%idx = getelementptr <2 x i1024>, <2 x i1024>* %a, i32 0, i32 0
 	%narrow = bitcast i1024* %idx to i64*
-	%val = load i64* %narrow
+	%val = load i64, i64* %narrow
 	call void @print_i64(i64 %val)
 
 	; Print second initialized element
-	%idx2 = getelementptr <2 x i1024>* %a, i32 0, i32 1
+	%idx2 = getelementptr <2 x i1024>, <2 x i1024>* %a, i32 0, i32 1
 	%narrow2 = bitcast i1024* %idx2 to i64*
-	%val2 = load i64* %narrow2
+	%val2 = load i64, i64* %narrow2
 	call void @print_i64(i64 %val2)
 
-	ret void	
+	ret void
 }
 
 define i32 @main() {
diff --git a/test/Concrete/FloatingPointOps.leq36.ll b/test/Concrete/FloatingPointOps.leq36.ll
new file mode 100644
index 00000000..b81a3b8d
--- /dev/null
+++ b/test/Concrete/FloatingPointOps.leq36.ll
@@ -0,0 +1,678 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
+
+; casting error messages
+@.strTrunc     = internal constant [15 x i8] c"FPTrunc broken\00"
+@.strExt       = internal constant [13 x i8] c"FPExt broken\00"
+@.strFPToUIFlt = internal constant [20 x i8] c"FPToUI float broken\00"
+@.strFPToUIDbl = internal constant [21 x i8] c"FPToUI double broken\00"
+@.strFPToSIFlt = internal constant [20 x i8] c"FPToSI float broken\00"
+@.strFPToSIDbl = internal constant [21 x i8] c"FPToSI double broken\00"
+@.strUIToFPFlt = internal constant [20 x i8] c"UIToFP float broken\00"
+@.strUIToFPDbl = internal constant [21 x i8] c"UIToFP double broken\00"
+@.strSIToFPFlt = internal constant [20 x i8] c"SIToFP float broken\00"
+@.strSIToFPDbl = internal constant [21 x i8] c"SIToFP double broken\00"
+
+; mathematical operator error messages
+@.strDivFlt    = internal constant [18 x i8] c"FDiv float broken\00"
+@.strDivDbl    = internal constant [19 x i8] c"FDiv double broken\00"
+@.strRemFlt    = internal constant [18 x i8] c"FRem float broken\00"
+@.strRemDbl    = internal constant [19 x i8] c"FRem double broken\00"
+@.strAddInt    = internal constant [16 x i8] c"Add ints broken\00"
+@.strAddFlt    = internal constant [18 x i8] c"Add floats broken\00"
+@.strAddDbl    = internal constant [19 x i8] c"Add doubles broken\00"
+@.strSubInt    = internal constant [16 x i8] c"Sub ints broken\00"
+@.strSubFlt    = internal constant [18 x i8] c"Sub floats broken\00"
+@.strSubDbl    = internal constant [19 x i8] c"Sub doubles broken\00"
+@.strMulInt    = internal constant [16 x i8] c"Mul ints broken\00"
+@.strMulFlt    = internal constant [18 x i8] c"Mul floats broken\00"
+@.strMulDbl    = internal constant [19 x i8] c"Mul doubles broken\00"
+
+; fcmp error messages
+@.strCmpTrFlt  = internal constant [19 x i8] c"floats TRUE broken\00" ; fcmp::generic broken msgs
+@.strCmpFaFlt  = internal constant [20 x i8] c"floats FALSE broken\00"
+@.strCmpTrDbl  = internal constant [19 x i8] c"double TRUE broken\00"
+@.strCmpFaDbl  = internal constant [20 x i8] c"double FALSE broken\00"
+@.strCmpEqFlt  = internal constant [17 x i8] c"floats == broken\00" ; fcmp::ordered broken msgs
+@.strCmpGeFlt  = internal constant [17 x i8] c"floats >= broken\00"
+@.strCmpGtFlt  = internal constant [17 x i8] c"floats >  broken\00"
+@.strCmpLeFlt  = internal constant [17 x i8] c"floats <= broken\00"
+@.strCmpLtFlt  = internal constant [17 x i8] c"floats <  broken\00"
+@.strCmpNeFlt  = internal constant [17 x i8] c"floats != broken\00"
+@.strCmpOrdFlt = internal constant [18 x i8] c"floats ORD broken\00"
+@.strCmpEqDbl  = internal constant [18 x i8] c"doubles == broken\00"
+@.strCmpGeDbl  = internal constant [18 x i8] c"doubles >= broken\00"
+@.strCmpGtDbl  = internal constant [18 x i8] c"doubles >  broken\00"
+@.strCmpLeDbl  = internal constant [18 x i8] c"doubles <= broken\00"
+@.strCmpLtDbl  = internal constant [18 x i8] c"doubles <  broken\00"
+@.strCmpNeDbl  = internal constant [18 x i8] c"doubles != broken\00"
+@.strCmpOrdDbl = internal constant [19 x i8] c"doubles ORD broken\00"
+@.strCmpEqFltU = internal constant [17 x i8] c"U:floats==broken\00" ; fcmp::unordered broken msgs
+@.strCmpGeFltU = internal constant [17 x i8] c"U:floats>=broken\00"
+@.strCmpGtFltU = internal constant [17 x i8] c"U:floats> broken\00"
+@.strCmpLeFltU = internal constant [17 x i8] c"U:floats<=broken\00"
+@.strCmpLtFltU = internal constant [17 x i8] c"U:floats< broken\00"
+@.strCmpNeFltU = internal constant [17 x i8] c"U:floats!=broken\00"
+@.strCmpUnoFlt = internal constant [20 x i8] c"U:floats UNO broken\00"
+@.strCmpEqDblU = internal constant [18 x i8] c"U:doubles==broken\00"
+@.strCmpGeDblU = internal constant [18 x i8] c"U:doubles>=broken\00"
+@.strCmpGtDblU = internal constant [18 x i8] c"U:doubles> broken\00"
+@.strCmpLeDblU = internal constant [18 x i8] c"U:doubles<=broken\00"
+@.strCmpLtDblU = internal constant [18 x i8] c"U:doubles< broken\00"
+@.strCmpNeDblU = internal constant [18 x i8] c"U:doubles!=broken\00"
+@.strCmpUnoDbl = internal constant [21 x i8] c"U:doubles UNO broken\00"
+
+@.strWorks     = internal constant [20 x i8] c"Everything works!\0D\0A\00"
+@.strNL        = internal constant [3 x i8]  c"\0D\0A\00"
+
+declare i32 @printf(i8*, ...)
+declare void @exit(i32)
+
+; if isOk is false, then print errMsg to stdout and exit(1)
+define void @failCheck(i1 %isOk, i8* %errMsg) {
+entry:
+  %fail = icmp eq i1 %isOk, 0
+  br i1 %fail, label %failed, label %return
+
+failed:
+  ; print the error msg
+  %ret = call i32 (i8*, ...)* @printf( i8* %errMsg )
+
+  ; add a newline to the ostream
+  %nl = getelementptr [3 x i8]* @.strNL, i32 0, i32 0
+  %ret2 = call i32 (i8*, ...)* @printf( i8* %nl )
+
+  ; exit with return value 1 to denote that an error occurred
+  call void @exit( i32 1 )
+  unreachable
+
+return:
+  ret void
+}
+
+; test FPTrunc which casts doubles to floats
+define void @testFPTrunc() {
+entry:
+  %d_addr = alloca double, align 8
+  store double 8.000000e+00, double* %d_addr
+  %d = load double* %d_addr
+  %f = fptrunc double %d to float
+  %matches = fcmp oeq float %f, 8.000000e+00
+  %err_msg = getelementptr [15 x i8]* @.strTrunc, i32 0, i32 0
+  call void @failCheck( i1 %matches, i8* %err_msg )
+  ret void
+}
+
+; test FPExt which casts floats to doubles
+define void @testFPExt() {
+entry:
+  %f_addr = alloca float, align 4
+  store float 8.000000e+00, float* %f_addr
+  %f = load float* %f_addr
+  %d = fpext float %f to double
+  %matches = fcmp oeq double %d, 8.000000e+00
+  %err_msg = getelementptr [13 x i8]* @.strExt, i32 0, i32 0
+  call void @failCheck( i1 %matches, i8* %err_msg )
+  ret void
+}
+
+; test casting fp to an unsigned int
+define void @testFPToUI() {
+entry:
+  %f_addr = alloca float, align 4
+  %d_addr = alloca double, align 8
+
+  ; test float to UI
+  store float 0x4020333340000000, float* %f_addr; %f = 8.1
+  %f = load float* %f_addr
+  %uf = fptoui float %f to i32
+  %matchesf = icmp eq i32 %uf, 8
+  %err_msgf = getelementptr [20 x i8]* @.strFPToUIFlt, i32 0, i32 0
+  call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+  ; test double to UI
+  store double 8.100000e+00, double* %d_addr
+  %d = load double* %d_addr
+  %ud = fptoui double %d to i32
+  %matchesd = icmp eq i32 %ud, 8
+  %err_msgd = getelementptr [21 x i8]* @.strFPToUIDbl, i32 0, i32 0
+  call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+  ret void
+}
+
+; test casting fp to a signed int
+define void @testFPToSI() {
+entry:
+  %f_addr = alloca float, align 4
+  %d_addr = alloca double, align 8
+
+  ; test float 8.1 to signed int
+  store float 0x4020333340000000, float* %f_addr
+  %f = load float* %f_addr
+  %sf = fptosi float %f to i32
+  %matchesf = icmp eq i32 %sf, 8
+  %err_msgf = getelementptr [20 x i8]* @.strFPToSIFlt, i32 0, i32 0
+  call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+  ; test double -8.1 to signed int
+  store double -8.100000e+00, double* %d_addr
+  %d = load double* %d_addr
+  %sd = fptosi double %d to i32
+  %matchesd = icmp eq i32 %sd, -8
+  %err_msgd = getelementptr [21 x i8]* @.strFPToSIDbl, i32 0, i32 0
+  call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+  ret void
+}
+
+; test casting unsigned int to fp
+define void @testUIToFP() {
+entry:
+  ; unsigned int to float
+  %f = uitofp i32 7 to float
+  %matchesf = fcmp oeq float %f, 7.000000e+00
+  %err_msgf = getelementptr [20 x i8]* @.strUIToFPFlt, i32 0, i32 0
+  call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+  ; unsigned int to double
+  %d = uitofp i32 7 to double
+  %matchesd = fcmp oeq double %d, 7.000000e+00
+  %err_msgd = getelementptr [21 x i8]* @.strUIToFPDbl, i32 0, i32 0
+  call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+  ret void
+}
+
+; test casting signed int to fp
+define void @testSIToFP() {
+entry:
+  ; signed int to float
+  %f = sitofp i32 -7 to float
+  %matchesf = fcmp oeq float %f, -7.000000e+00
+  %err_msgf = getelementptr [20 x i8]* @.strSIToFPFlt, i32 0, i32 0
+  call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+  ; signed int to double
+  %d = sitofp i32 -7 to double
+  %matchesd = fcmp oeq double %d, -7.000000e+00
+  %err_msgd = getelementptr [21 x i8]* @.strSIToFPDbl, i32 0, i32 0
+  call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+  ret void
+}
+
+; testing fp division
+define void @testFDiv() {
+entry:
+  %fN_addr = alloca float, align 4
+  %fD_addr = alloca float, align 4
+  %dN_addr = alloca double, align 8
+  %dD_addr = alloca double, align 8
+
+  ; float division
+  store float 2.200000e+01, float* %fN_addr
+  store float 4.000000e+00, float* %fD_addr
+  %fN = load float* %fN_addr
+  %fD = load float* %fD_addr
+  %f = fdiv float %fN, %fD
+  %matchesf = fcmp oeq float %f, 5.500000e+00
+  %err_msgf = getelementptr [18 x i8]* @.strDivFlt, i32 0, i32 0
+  call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+  ; double division
+  store double 2.200000e+01, double* %dN_addr
+  store double -4.000000e+00, double* %dD_addr
+  %dN = load double* %dN_addr
+  %dD = load double* %dD_addr
+  %d = fdiv double %dN, %dD
+  %matchesd = fcmp oeq double %d, -5.500000e+00
+  %err_msgd = getelementptr [19 x i8]* @.strDivDbl, i32 0, i32 0
+  call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+  ret void
+}
+
+; testing fp modulo
+define void @testFRem() {
+entry:
+  %fN_addr = alloca float, align 4
+  %fD_addr = alloca float, align 4
+  %dN_addr = alloca double, align 8
+  %dD_addr = alloca double, align 8
+
+  ; float modoulo
+  store float 2.200000e+01, float* %fN_addr
+  store float 4.000000e+00, float* %fD_addr
+  %fN = load float* %fN_addr
+  %fD = load float* %fD_addr
+  %f = frem float %fN, %fD
+  %matchesf = fcmp oeq float %f, 2.000000e+00
+  %err_msgf = getelementptr [18 x i8]* @.strRemFlt, i32 0, i32 0
+  call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+  ; double modulo
+  store double -2.200000e+01, double* %dN_addr
+  store double 4.000000e+00, double* %dD_addr
+  %dN = load double* %dN_addr
+  %dD = load double* %dD_addr
+  %d = frem double %dN, %dD
+  %matchesd = fcmp oeq double %d, -2.000000e+00
+  %err_msgd = getelementptr [19 x i8]* @.strRemDbl, i32 0, i32 0
+  call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+  ret void
+}
+
+; test addition
+define void @testAdd() {
+entry:
+  %f1_addr = alloca float, align 4
+  %f2_addr = alloca float, align 4
+  %d1_addr = alloca double, align 8
+  %d2_addr = alloca double, align 8
+
+  ; test integer addition (3 + 4)
+  %sumi = add i32 3, 4
+  %matchesi = icmp eq i32 %sumi, 7
+  %err_msgi = getelementptr [16 x i8]* @.strAddInt, i32 0, i32 0
+  call void @failCheck( i1 %matchesi, i8* %err_msgi )
+
+  ; test float addition (3.5 + 4.2)
+  store float 3.500000e+00, float* %f1_addr
+  store float 0x4010CCCCC0000000, float* %f2_addr
+  %f1 = load float* %f1_addr
+  %f2 = load float* %f2_addr
+  %sumf = fadd float %f1, %f2
+  %matchesf = fcmp oeq float %sumf, 0x401ECCCCC0000000
+  %err_msgf = getelementptr [18 x i8]* @.strAddFlt, i32 0, i32 0
+  call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+  ; test double addition (3.5 + -4.2)
+  store double 3.500000e+00, double* %d1_addr
+  store double -4.200000e+00, double* %d2_addr
+  %d1 = load double* %d1_addr
+  %d2 = load double* %d2_addr
+  %sumd = fadd double %d1, %d2
+  %matchesd = fcmp oeq double %sumd, 0xBFE6666666666668
+  %err_msgd = getelementptr [19 x i8]* @.strAddDbl, i32 0, i32 0
+  call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+  ret void
+}
+
+; test subtraction
+define void @testSub() {
+entry:
+  %f1_addr = alloca float, align 4
+  %f2_addr = alloca float, align 4
+  %d1_addr = alloca double, align 8
+  %d2_addr = alloca double, align 8
+
+  ; test integer subtraction (3 - 4)
+  %subi = sub i32 3, 4
+  %matchesi = icmp eq i32 %subi, -1
+  %err_msgi = getelementptr [16 x i8]* @.strSubInt, i32 0, i32 0
+  call void @failCheck( i1 %matchesi, i8* %err_msgi )
+
+  ; test float subtraction (3.5 - 4.2)
+  store float 3.500000e+00, float* %f1_addr
+  store float 0x4010CCCCC0000000, float* %f2_addr
+  %f1 = load float* %f1_addr
+  %f2 = load float* %f2_addr
+  %subf = fsub float %f1, %f2
+  %matchesf = fcmp oeq float %subf, 0xBFE6666600000000
+  %err_msgf = getelementptr [18 x i8]* @.strSubFlt, i32 0, i32 0
+  call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+  ; test double subtraction (3.5 - -4.2)
+  store double 3.500000e+00, double* %d1_addr
+  store double -4.200000e+00, double* %d2_addr
+  %d1 = load double* %d1_addr
+  %d2 = load double* %d2_addr
+  %subd = fsub double %d1, %d2
+  %matchesd = fcmp oeq double %subd, 7.700000e+00
+  %err_msgd = getelementptr [19 x i8]* @.strSubDbl, i32 0, i32 0
+  call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+  ret void
+}
+
+; test multiplication
+define void @testMul() {
+entry:
+  %f1_addr = alloca float, align 4
+  %f2_addr = alloca float, align 4
+  %d1_addr = alloca double, align 8
+  %d2_addr = alloca double, align 8
+
+  ; test integer multiplication (3 * 4)
+  %muli = mul i32 3, 4
+  %matchesi = icmp eq i32 %muli, 12
+  %err_msgi = getelementptr [16 x i8]* @.strMulInt, i32 0, i32 0
+  call void @failCheck( i1 %matchesi, i8* %err_msgi )
+
+  ; test float multiplication (3.5 * 4.2)
+  store float 3.500000e+00, float* %f1_addr
+  store float 0x4010CCCCC0000000, float* %f2_addr
+  %f1 = load float* %f1_addr
+  %f2 = load float* %f2_addr
+  %mulf = fmul float %f1, %f2
+  %matchesf = fcmp oeq float %mulf, 0x402D666640000000
+  %err_msgf = getelementptr [18 x i8]* @.strMulFlt, i32 0, i32 0
+  call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+  ; test double multiplication (3.5 * -4.2)
+  store double 3.500000e+00, double* %d1_addr
+  store double -4.200000e+00, double* %d2_addr
+  %d1 = load double* %d1_addr
+  %d2 = load double* %d2_addr
+  %muld = fmul double %d1, %d2
+  %matchesd = fcmp oeq double %muld, 0xC02D666666666667
+  %err_msgd = getelementptr [19 x i8]* @.strMulDbl, i32 0, i32 0
+  call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+  ret void
+}
+
+; test float comparisons (ordered)
+define void @testFCmpFOrdered(float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord) {
+entry:
+  ; test fcmp::true -- should always return true
+  %cmp_t    = fcmp true float %f1, %f2
+  %cmp_t_ok = icmp eq i1 %cmp_t, 1
+  %cmp_t_em = getelementptr [19 x i8]* @.strCmpTrFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_t_ok, i8* %cmp_t_em )
+
+  ; test fcmp::false -- should always return false
+  %cmp_f    = fcmp false float %f1, %f2
+  %cmp_f_ok = icmp eq i1 %cmp_f, 0
+  %cmp_f_em = getelementptr [20 x i8]* @.strCmpFaFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_f_ok, i8* %cmp_f_em )
+
+  ; test fcmp::ord -- should return true if neither operand is NaN
+  %cmp_o    = fcmp ord float %f1, %f2
+  %cmp_o_ok = icmp eq i1 %cmp_o, %ord
+  %cmp_o_em = getelementptr [18 x i8]* @.strCmpOrdFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
+
+  ; test fcmp::oeq -- should return true if neither operand is a NaN and they are equal
+  %cmp_eq    = fcmp oeq float %f1, %f2
+  %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
+  %cmp_eq_em = getelementptr [17 x i8]* @.strCmpEqFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
+
+  ; test fcmp::oge -- should return true if neither operand is a NaN and the first is greater or equal
+  %cmp_ge    = fcmp oge float %f1, %f2
+  %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
+  %cmp_ge_em = getelementptr [17 x i8]* @.strCmpGeFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
+
+  ; test fcmp::ogt -- should return true if neither operand is a NaN and the first is greater
+  %cmp_gt    = fcmp ogt float %f1, %f2
+  %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
+  %cmp_gt_em = getelementptr [17 x i8]* @.strCmpGtFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
+
+  ; test fcmp::ole -- should return true if neither operand is a NaN and the first is less or equal
+  %cmp_le    = fcmp ole float %f1, %f2
+  %cmp_le_ok = icmp eq i1 %cmp_le, %le
+  %cmp_le_em = getelementptr [17 x i8]* @.strCmpLeFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
+
+  ; test fcmp::olt -- should return true if neither operand is a NaN and the first is less
+  %cmp_lt    = fcmp olt float %f1, %f2
+  %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
+  %cmp_lt_em = getelementptr [17 x i8]* @.strCmpLtFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
+
+  ; test fcmp::one -- should return true if neither operand is a NaN and they are not equal
+  %cmp_ne    = fcmp one float %f1, %f2
+  %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
+  %cmp_ne_em = getelementptr [17 x i8]* @.strCmpNeFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
+
+  ret void
+}
+
+; test double comparisons (ordered)
+define void @testFCmpDOrdered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord) {
+entry:
+  ; test fcmp::true -- should always return true
+  %cmp_t    = fcmp true double %d1, %d2
+  %cmp_t_ok = icmp eq i1 %cmp_t, 1
+  %cmp_t_em = getelementptr [19 x i8]* @.strCmpTrDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_t_ok, i8* %cmp_t_em )
+
+  ; test fcmp::false -- should always return false
+  %cmp_f    = fcmp false double %d1, %d2
+  %cmp_f_ok = icmp eq i1 %cmp_f, 0
+  %cmp_f_em = getelementptr [20 x i8]* @.strCmpFaDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_f_ok, i8* %cmp_f_em )
+
+  ; test fcmp::ord -- should return true if neither operand is NaN
+  %cmp_o    = fcmp ord double %d1, %d2
+  %cmp_o_ok = icmp eq i1 %cmp_o, %ord
+  %cmp_o_em = getelementptr [19 x i8]* @.strCmpOrdDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
+
+  ; test fcmp::oeq -- should return true if neither operand is a NaN and they are equal
+  %cmp_eq    = fcmp oeq double %d1, %d2
+  %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
+  %cmp_eq_em = getelementptr [18 x i8]* @.strCmpEqDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
+
+  ; test fcmp::oge -- should return true if neither operand is a NaN and the first is greater or equal
+  %cmp_ge    = fcmp oge double %d1, %d2
+  %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
+  %cmp_ge_em = getelementptr [18 x i8]* @.strCmpGeDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
+
+  ; test fcmp::ogt -- should return true if neither operand is a NaN and the first is greater
+  %cmp_gt    = fcmp ogt double %d1, %d2
+  %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
+  %cmp_gt_em = getelementptr [18 x i8]* @.strCmpGtDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
+
+  ; test fcmp::ole -- should return true if neither operand is a NaN and the first is less or equal
+  %cmp_le    = fcmp ole double %d1, %d2
+  %cmp_le_ok = icmp eq i1 %cmp_le, %le
+  %cmp_le_em = getelementptr [18 x i8]* @.strCmpLeDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
+
+  ; test fcmp::olt -- should return true if neither operand is a NaN and the first is less
+  %cmp_lt    = fcmp olt double %d1, %d2
+  %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
+  %cmp_lt_em = getelementptr [18 x i8]* @.strCmpLtDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
+
+  ; test fcmp::one -- should return true if neither operand is a NaN and they are not equal
+  %cmp_ne    = fcmp one double %d1, %d2
+  %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
+  %cmp_ne_em = getelementptr [18 x i8]* @.strCmpNeDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
+
+  ret void
+}
+
+; test floating point comparisons (ordered)
+define void @testFCmpBothOrdered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord) {
+entry:
+  call void @testFCmpDOrdered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord )
+
+  %f1 = fptrunc double %d1 to float
+  %f2 = fptrunc double %d2 to float
+  call void @testFCmpFOrdered( float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord )
+
+  ret void
+}
+
+; test float comparisons (unordered)
+define void @testFCmpFUnordered(float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno) {
+entry:
+  ; test fcmp::uno -- should return true if either operand is NaN
+  %cmp_o    = fcmp uno float %f1, %f2
+  %cmp_o_ok = icmp eq i1 %cmp_o, %uno
+  %cmp_o_em = getelementptr [20 x i8]* @.strCmpUnoFlt, i32 0, i32 0
+  call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
+
+  ; test fcmp::oeq -- should return true if either operand is a NaN and they are equal
+  %cmp_eq    = fcmp ueq float %f1, %f2
+  %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
+  %cmp_eq_em = getelementptr [17 x i8]* @.strCmpEqFltU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
+
+  ; test fcmp::oge -- should return true if either operand is a NaN and the first is greater or equal
+  %cmp_ge    = fcmp uge float %f1, %f2
+  %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
+  %cmp_ge_em = getelementptr [17 x i8]* @.strCmpGeFltU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
+
+  ; test fcmp::ogt -- should return true if either operand is a NaN and the first is greater
+  %cmp_gt    = fcmp ugt float %f1, %f2
+  %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
+  %cmp_gt_em = getelementptr [17 x i8]* @.strCmpGtFltU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
+
+  ; test fcmp::ole -- should return true if either operand is a NaN and the first is less or equal
+  %cmp_le    = fcmp ule float %f1, %f2
+  %cmp_le_ok = icmp eq i1 %cmp_le, %le
+  %cmp_le_em = getelementptr [17 x i8]* @.strCmpLeFltU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
+
+  ; test fcmp::olt -- should return true if either operand is a NaN and the first is less
+  %cmp_lt    = fcmp ult float %f1, %f2
+  %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
+  %cmp_lt_em = getelementptr [17 x i8]* @.strCmpLtFltU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
+
+  ; test fcmp::one -- should return true if either operand is a NaN and they are not equal
+  %cmp_ne    = fcmp une float %f1, %f2
+  %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
+  %cmp_ne_em = getelementptr [17 x i8]* @.strCmpNeFltU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
+
+  ret void
+}
+
+; test double comparisons (unordered)
+define void @testFCmpDUnordered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno) {
+entry:
+  ; test fcmp::uno -- should return true if either operand is NaN
+  %cmp_o    = fcmp uno double %d1, %d2
+  %cmp_o_ok = icmp eq i1 %cmp_o, %uno
+  %cmp_o_em = getelementptr [21 x i8]* @.strCmpUnoDbl, i32 0, i32 0
+  call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
+
+  ; test fcmp::ueq -- should return true if either operand is a NaN and they are equal
+  %cmp_eq    = fcmp ueq double %d1, %d2
+  %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
+  %cmp_eq_em = getelementptr [18 x i8]* @.strCmpEqDblU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
+
+  ; test fcmp::uge -- should return true if either operand is a NaN and the first is greater or equal
+  %cmp_ge    = fcmp uge double %d1, %d2
+  %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
+  %cmp_ge_em = getelementptr [18 x i8]* @.strCmpGeDblU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
+
+  ; test fcmp::ugt -- should return true if either operand is a NaN and the first is greater
+  %cmp_gt    = fcmp ugt double %d1, %d2
+  %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
+  %cmp_gt_em = getelementptr [18 x i8]* @.strCmpGtDblU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
+
+  ; test fcmp::ule -- should return true if either operand is a NaN and the first is less or equal
+  %cmp_le    = fcmp ule double %d1, %d2
+  %cmp_le_ok = icmp eq i1 %cmp_le, %le
+  %cmp_le_em = getelementptr [18 x i8]* @.strCmpLeDblU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
+
+  ; test fcmp::ult -- should return true if either operand is a NaN and the first is less
+  %cmp_lt    = fcmp ult double %d1, %d2
+  %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
+  %cmp_lt_em = getelementptr [18 x i8]* @.strCmpLtDblU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
+
+  ; test fcmp::une -- should return true if either operand is a NaN and they are not equal
+  %cmp_ne    = fcmp une double %d1, %d2
+  %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
+  %cmp_ne_em = getelementptr [18 x i8]* @.strCmpNeDblU, i32 0, i32 0
+  call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
+
+  ret void
+}
+
+; test floating point comparisons (unordered)
+define void @testFCmpBothUnordered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno) {
+entry:
+  call void @testFCmpDUnordered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno )
+
+  %f1 = fptrunc double %d1 to float
+  %f2 = fptrunc double %d2 to float
+  call void @testFCmpFUnordered( float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno )
+
+  ret void
+}
+
+; test floating point comparisons (ordered and unordered)
+define void @testFCmpBoth(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord, i1 %uno) {
+entry:
+  call void @testFCmpBothOrdered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord )
+  call void @testFCmpBothUnordered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno )
+
+  ret void
+}
+
+; test floating point comparisons (ordered and unordered) with a variety of real numbers and NaNs as operands
+define void @testFCmp() {
+entry:
+  %x = alloca i64, align 8
+  %nan = alloca double, align 8
+
+  ; test FCmp on some real number inputs
+  call void @testFCmpBoth( double 0.000000e+00, double 0.000000e+00, i1 1, i1 1, i1 0, i1 1, i1 0, i1 0, i1 1, i1 0 )
+  call void @testFCmpBoth( double 0.000000e+00, double 1.000000e+00, i1 0, i1 0, i1 0, i1 1, i1 1, i1 1, i1 1, i1 0 )
+  call void @testFCmpBoth( double 1.000000e+00, double 0.000000e+00, i1 0, i1 1, i1 1, i1 0, i1 0, i1 1, i1 1, i1 0 )
+
+  ; build NaN
+  %nan_as_i64 = bitcast double* %nan to i64*
+  store i64 -1, i64* %nan_as_i64
+
+  ; load two copies of our NaN
+  %nan1 = load double* %nan
+  %nan2 = load double* %nan
+
+  ; NaNs do different things depending on ordered vs unordered
+  call void @testFCmpBothOrdered( double %nan1, double 0.000000e+00, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0 )
+  call void @testFCmpBothOrdered( double %nan1, double %nan2, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0 )
+  call void @testFCmpBothUnordered( double %nan1, double 0.000000e+00, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1 )
+  call void @testFCmpBothUnordered( double %nan1, double %nan2, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1 )
+
+  ret void
+}
+
+; test all floating point instructions
+define i32 @main() {
+entry:
+  call void @testFPTrunc( )
+  call void @testFPExt( )
+  call void @testFPToUI( )
+  call void @testFPToSI( )
+  call void @testUIToFP( )
+  call void @testSIToFP( )
+
+  call void @testFDiv( )
+  call void @testFRem( )
+  call void @testAdd( )
+  call void @testSub( )
+  call void @testMul( )
+
+  call void @testFCmp( )
+
+  ; everything worked -- print a message saying so
+  %works_msg = getelementptr [20 x i8]* @.strWorks, i32 0, i32 0
+  %ret = call i32 (i8*, ...)* @printf( i8* %works_msg )
+
+  ret i32 0
+}
diff --git a/test/Concrete/FloatingPointOps.ll b/test/Concrete/FloatingPointOps.ll
index 00d4e877..4c96e336 100644
--- a/test/Concrete/FloatingPointOps.ll
+++ b/test/Concrete/FloatingPointOps.ll
@@ -1,3 +1,7 @@
+; LLVM 3.7 requires a type as the first argument to 'load'
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; LLVM 3.7 no longer accepts '*' with a 'call'
+; REQUIRES: geq-llvm-3.7
 ; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
 
 ; casting error messages
@@ -75,11 +79,11 @@ entry:
 
 failed:
   ; print the error msg
-  %ret = call i32 (i8*, ...)* @printf( i8* %errMsg )
+  %ret = call i32 (i8*, ...) @printf( i8* %errMsg )
 
   ; add a newline to the ostream
-  %nl = getelementptr [3 x i8]* @.strNL, i32 0, i32 0
-  %ret2 = call i32 (i8*, ...)* @printf( i8* %nl )
+  %nl = getelementptr [3 x i8], [3 x i8]* @.strNL, i32 0, i32 0
+  %ret2 = call i32 (i8*, ...) @printf( i8* %nl )
 
   ; exit with return value 1 to denote that an error occurred
   call void @exit( i32 1 )
@@ -94,10 +98,10 @@ define void @testFPTrunc() {
 entry:
   %d_addr = alloca double, align 8
   store double 8.000000e+00, double* %d_addr
-  %d = load double* %d_addr
+  %d = load double, double* %d_addr
   %f = fptrunc double %d to float
   %matches = fcmp oeq float %f, 8.000000e+00
-  %err_msg = getelementptr [15 x i8]* @.strTrunc, i32 0, i32 0
+  %err_msg = getelementptr [15 x i8], [15 x i8]* @.strTrunc, i32 0, i32 0
   call void @failCheck( i1 %matches, i8* %err_msg )
   ret void
 }
@@ -107,10 +111,10 @@ define void @testFPExt() {
 entry:
   %f_addr = alloca float, align 4
   store float 8.000000e+00, float* %f_addr
-  %f = load float* %f_addr
+  %f = load float, float* %f_addr
   %d = fpext float %f to double
   %matches = fcmp oeq double %d, 8.000000e+00
-  %err_msg = getelementptr [13 x i8]* @.strExt, i32 0, i32 0
+  %err_msg = getelementptr [13 x i8], [13 x i8]* @.strExt, i32 0, i32 0
   call void @failCheck( i1 %matches, i8* %err_msg )
   ret void
 }
@@ -123,18 +127,18 @@ entry:
 
   ; test float to UI
   store float 0x4020333340000000, float* %f_addr; %f = 8.1
-  %f = load float* %f_addr
+  %f = load float, float* %f_addr
   %uf = fptoui float %f to i32
   %matchesf = icmp eq i32 %uf, 8
-  %err_msgf = getelementptr [20 x i8]* @.strFPToUIFlt, i32 0, i32 0
+  %err_msgf = getelementptr [20 x i8], [20 x i8]* @.strFPToUIFlt, i32 0, i32 0
   call void @failCheck( i1 %matchesf, i8* %err_msgf )
 
   ; test double to UI
   store double 8.100000e+00, double* %d_addr
-  %d = load double* %d_addr
+  %d = load double, double* %d_addr
   %ud = fptoui double %d to i32
   %matchesd = icmp eq i32 %ud, 8
-  %err_msgd = getelementptr [21 x i8]* @.strFPToUIDbl, i32 0, i32 0
+  %err_msgd = getelementptr [21 x i8], [21 x i8]* @.strFPToUIDbl, i32 0, i32 0
   call void @failCheck( i1 %matchesd, i8* %err_msgd )
 
   ret void
@@ -148,18 +152,18 @@ entry:
 
   ; test float 8.1 to signed int
   store float 0x4020333340000000, float* %f_addr
-  %f = load float* %f_addr
+  %f = load float, float* %f_addr
   %sf = fptosi float %f to i32
   %matchesf = icmp eq i32 %sf, 8
-  %err_msgf = getelementptr [20 x i8]* @.strFPToSIFlt, i32 0, i32 0
+  %err_msgf = getelementptr [20 x i8], [20 x i8]* @.strFPToSIFlt, i32 0, i32 0
   call void @failCheck( i1 %matchesf, i8* %err_msgf )
 
   ; test double -8.1 to signed int
   store double -8.100000e+00, double* %d_addr
-  %d = load double* %d_addr
+  %d = load double, double* %d_addr
   %sd = fptosi double %d to i32
   %matchesd = icmp eq i32 %sd, -8
-  %err_msgd = getelementptr [21 x i8]* @.strFPToSIDbl, i32 0, i32 0
+  %err_msgd = getelementptr [21 x i8], [21 x i8]* @.strFPToSIDbl, i32 0, i32 0
   call void @failCheck( i1 %matchesd, i8* %err_msgd )
 
   ret void
@@ -171,13 +175,13 @@ entry:
   ; unsigned int to float
   %f = uitofp i32 7 to float
   %matchesf = fcmp oeq float %f, 7.000000e+00
-  %err_msgf = getelementptr [20 x i8]* @.strUIToFPFlt, i32 0, i32 0
+  %err_msgf = getelementptr [20 x i8], [20 x i8]* @.strUIToFPFlt, i32 0, i32 0
   call void @failCheck( i1 %matchesf, i8* %err_msgf )
 
   ; unsigned int to double
   %d = uitofp i32 7 to double
   %matchesd = fcmp oeq double %d, 7.000000e+00
-  %err_msgd = getelementptr [21 x i8]* @.strUIToFPDbl, i32 0, i32 0
+  %err_msgd = getelementptr [21 x i8], [21 x i8]* @.strUIToFPDbl, i32 0, i32 0
   call void @failCheck( i1 %matchesd, i8* %err_msgd )
 
   ret void
@@ -189,13 +193,13 @@ entry:
   ; signed int to float
   %f = sitofp i32 -7 to float
   %matchesf = fcmp oeq float %f, -7.000000e+00
-  %err_msgf = getelementptr [20 x i8]* @.strSIToFPFlt, i32 0, i32 0
+  %err_msgf = getelementptr [20 x i8], [20 x i8]* @.strSIToFPFlt, i32 0, i32 0
   call void @failCheck( i1 %matchesf, i8* %err_msgf )
 
   ; signed int to double
   %d = sitofp i32 -7 to double
   %matchesd = fcmp oeq double %d, -7.000000e+00
-  %err_msgd = getelementptr [21 x i8]* @.strSIToFPDbl, i32 0, i32 0
+  %err_msgd = getelementptr [21 x i8], [21 x i8]* @.strSIToFPDbl, i32 0, i32 0
   call void @failCheck( i1 %matchesd, i8* %err_msgd )
 
   ret void
@@ -212,21 +216,21 @@ entry:
   ; float division
   store float 2.200000e+01, float* %fN_addr
   store float 4.000000e+00, float* %fD_addr
-  %fN = load float* %fN_addr
-  %fD = load float* %fD_addr
+  %fN = load float, float* %fN_addr
+  %fD = load float, float* %fD_addr
   %f = fdiv float %fN, %fD
   %matchesf = fcmp oeq float %f, 5.500000e+00
-  %err_msgf = getelementptr [18 x i8]* @.strDivFlt, i32 0, i32 0
+  %err_msgf = getelementptr [18 x i8], [18 x i8]* @.strDivFlt, i32 0, i32 0
   call void @failCheck( i1 %matchesf, i8* %err_msgf )
 
   ; double division
   store double 2.200000e+01, double* %dN_addr
   store double -4.000000e+00, double* %dD_addr
-  %dN = load double* %dN_addr
-  %dD = load double* %dD_addr
+  %dN = load double, double* %dN_addr
+  %dD = load double, double* %dD_addr
   %d = fdiv double %dN, %dD
   %matchesd = fcmp oeq double %d, -5.500000e+00
-  %err_msgd = getelementptr [19 x i8]* @.strDivDbl, i32 0, i32 0
+  %err_msgd = getelementptr [19 x i8], [19 x i8]* @.strDivDbl, i32 0, i32 0
   call void @failCheck( i1 %matchesd, i8* %err_msgd )
 
   ret void
@@ -243,21 +247,21 @@ entry:
   ; float modoulo
   store float 2.200000e+01, float* %fN_addr
   store float 4.000000e+00, float* %fD_addr
-  %fN = load float* %fN_addr
-  %fD = load float* %fD_addr
+  %fN = load float, float* %fN_addr
+  %fD = load float, float* %fD_addr
   %f = frem float %fN, %fD
   %matchesf = fcmp oeq float %f, 2.000000e+00
-  %err_msgf = getelementptr [18 x i8]* @.strRemFlt, i32 0, i32 0
+  %err_msgf = getelementptr [18 x i8], [18 x i8]* @.strRemFlt, i32 0, i32 0
   call void @failCheck( i1 %matchesf, i8* %err_msgf )
 
   ; double modulo
   store double -2.200000e+01, double* %dN_addr
   store double 4.000000e+00, double* %dD_addr
-  %dN = load double* %dN_addr
-  %dD = load double* %dD_addr
+  %dN = load double, double* %dN_addr
+  %dD = load double, double* %dD_addr
   %d = frem double %dN, %dD
   %matchesd = fcmp oeq double %d, -2.000000e+00
-  %err_msgd = getelementptr [19 x i8]* @.strRemDbl, i32 0, i32 0
+  %err_msgd = getelementptr [19 x i8], [19 x i8]* @.strRemDbl, i32 0, i32 0
   call void @failCheck( i1 %matchesd, i8* %err_msgd )
 
   ret void
@@ -274,27 +278,27 @@ entry:
   ; test integer addition (3 + 4)
   %sumi = add i32 3, 4
   %matchesi = icmp eq i32 %sumi, 7
-  %err_msgi = getelementptr [16 x i8]* @.strAddInt, i32 0, i32 0
+  %err_msgi = getelementptr [16 x i8], [16 x i8]* @.strAddInt, i32 0, i32 0
   call void @failCheck( i1 %matchesi, i8* %err_msgi )
 
   ; test float addition (3.5 + 4.2)
   store float 3.500000e+00, float* %f1_addr
   store float 0x4010CCCCC0000000, float* %f2_addr
-  %f1 = load float* %f1_addr
-  %f2 = load float* %f2_addr
+  %f1 = load float, float* %f1_addr
+  %f2 = load float, float* %f2_addr
   %sumf = fadd float %f1, %f2
   %matchesf = fcmp oeq float %sumf, 0x401ECCCCC0000000
-  %err_msgf = getelementptr [18 x i8]* @.strAddFlt, i32 0, i32 0
+  %err_msgf = getelementptr [18 x i8], [18 x i8]* @.strAddFlt, i32 0, i32 0
   call void @failCheck( i1 %matchesf, i8* %err_msgf )
 
   ; test double addition (3.5 + -4.2)
   store double 3.500000e+00, double* %d1_addr
   store double -4.200000e+00, double* %d2_addr
-  %d1 = load double* %d1_addr
-  %d2 = load double* %d2_addr
+  %d1 = load double, double* %d1_addr
+  %d2 = load double, double* %d2_addr
   %sumd = fadd double %d1, %d2
   %matchesd = fcmp oeq double %sumd, 0xBFE6666666666668
-  %err_msgd = getelementptr [19 x i8]* @.strAddDbl, i32 0, i32 0
+  %err_msgd = getelementptr [19 x i8], [19 x i8]* @.strAddDbl, i32 0, i32 0
   call void @failCheck( i1 %matchesd, i8* %err_msgd )
 
   ret void
@@ -311,27 +315,27 @@ entry:
   ; test integer subtraction (3 - 4)
   %subi = sub i32 3, 4
   %matchesi = icmp eq i32 %subi, -1
-  %err_msgi = getelementptr [16 x i8]* @.strSubInt, i32 0, i32 0
+  %err_msgi = getelementptr [16 x i8], [16 x i8]* @.strSubInt, i32 0, i32 0
   call void @failCheck( i1 %matchesi, i8* %err_msgi )
 
   ; test float subtraction (3.5 - 4.2)
   store float 3.500000e+00, float* %f1_addr
   store float 0x4010CCCCC0000000, float* %f2_addr
-  %f1 = load float* %f1_addr
-  %f2 = load float* %f2_addr
+  %f1 = load float, float* %f1_addr
+  %f2 = load float, float* %f2_addr
   %subf = fsub float %f1, %f2
   %matchesf = fcmp oeq float %subf, 0xBFE6666600000000
-  %err_msgf = getelementptr [18 x i8]* @.strSubFlt, i32 0, i32 0
+  %err_msgf = getelementptr [18 x i8], [18 x i8]* @.strSubFlt, i32 0, i32 0
   call void @failCheck( i1 %matchesf, i8* %err_msgf )
 
   ; test double subtraction (3.5 - -4.2)
   store double 3.500000e+00, double* %d1_addr
   store double -4.200000e+00, double* %d2_addr
-  %d1 = load double* %d1_addr
-  %d2 = load double* %d2_addr
+  %d1 = load double, double* %d1_addr
+  %d2 = load double, double* %d2_addr
   %subd = fsub double %d1, %d2
   %matchesd = fcmp oeq double %subd, 7.700000e+00
-  %err_msgd = getelementptr [19 x i8]* @.strSubDbl, i32 0, i32 0
+  %err_msgd = getelementptr [19 x i8], [19 x i8]* @.strSubDbl, i32 0, i32 0
   call void @failCheck( i1 %matchesd, i8* %err_msgd )
 
   ret void
@@ -348,27 +352,27 @@ entry:
   ; test integer multiplication (3 * 4)
   %muli = mul i32 3, 4
   %matchesi = icmp eq i32 %muli, 12
-  %err_msgi = getelementptr [16 x i8]* @.strMulInt, i32 0, i32 0
+  %err_msgi = getelementptr [16 x i8], [16 x i8]* @.strMulInt, i32 0, i32 0
   call void @failCheck( i1 %matchesi, i8* %err_msgi )
 
   ; test float multiplication (3.5 * 4.2)
   store float 3.500000e+00, float* %f1_addr
   store float 0x4010CCCCC0000000, float* %f2_addr
-  %f1 = load float* %f1_addr
-  %f2 = load float* %f2_addr
+  %f1 = load float, float* %f1_addr
+  %f2 = load float, float* %f2_addr
   %mulf = fmul float %f1, %f2
   %matchesf = fcmp oeq float %mulf, 0x402D666640000000
-  %err_msgf = getelementptr [18 x i8]* @.strMulFlt, i32 0, i32 0
+  %err_msgf = getelementptr [18 x i8], [18 x i8]* @.strMulFlt, i32 0, i32 0
   call void @failCheck( i1 %matchesf, i8* %err_msgf )
 
   ; test double multiplication (3.5 * -4.2)
   store double 3.500000e+00, double* %d1_addr
   store double -4.200000e+00, double* %d2_addr
-  %d1 = load double* %d1_addr
-  %d2 = load double* %d2_addr
+  %d1 = load double, double* %d1_addr
+  %d2 = load double, double* %d2_addr
   %muld = fmul double %d1, %d2
   %matchesd = fcmp oeq double %muld, 0xC02D666666666667
-  %err_msgd = getelementptr [19 x i8]* @.strMulDbl, i32 0, i32 0
+  %err_msgd = getelementptr [19 x i8], [19 x i8]* @.strMulDbl, i32 0, i32 0
   call void @failCheck( i1 %matchesd, i8* %err_msgd )
 
   ret void
@@ -380,55 +384,55 @@ entry:
   ; test fcmp::true -- should always return true
   %cmp_t    = fcmp true float %f1, %f2
   %cmp_t_ok = icmp eq i1 %cmp_t, 1
-  %cmp_t_em = getelementptr [19 x i8]* @.strCmpTrFlt, i32 0, i32 0
+  %cmp_t_em = getelementptr [19 x i8], [19 x i8]* @.strCmpTrFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_t_ok, i8* %cmp_t_em )
 
   ; test fcmp::false -- should always return false
   %cmp_f    = fcmp false float %f1, %f2
   %cmp_f_ok = icmp eq i1 %cmp_f, 0
-  %cmp_f_em = getelementptr [20 x i8]* @.strCmpFaFlt, i32 0, i32 0
+  %cmp_f_em = getelementptr [20 x i8], [20 x i8]* @.strCmpFaFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_f_ok, i8* %cmp_f_em )
 
   ; test fcmp::ord -- should return true if neither operand is NaN
   %cmp_o    = fcmp ord float %f1, %f2
   %cmp_o_ok = icmp eq i1 %cmp_o, %ord
-  %cmp_o_em = getelementptr [18 x i8]* @.strCmpOrdFlt, i32 0, i32 0
+  %cmp_o_em = getelementptr [18 x i8], [18 x i8]* @.strCmpOrdFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
 
   ; test fcmp::oeq -- should return true if neither operand is a NaN and they are equal
   %cmp_eq    = fcmp oeq float %f1, %f2
   %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
-  %cmp_eq_em = getelementptr [17 x i8]* @.strCmpEqFlt, i32 0, i32 0
+  %cmp_eq_em = getelementptr [17 x i8], [17 x i8]* @.strCmpEqFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
 
   ; test fcmp::oge -- should return true if neither operand is a NaN and the first is greater or equal
   %cmp_ge    = fcmp oge float %f1, %f2
   %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
-  %cmp_ge_em = getelementptr [17 x i8]* @.strCmpGeFlt, i32 0, i32 0
+  %cmp_ge_em = getelementptr [17 x i8], [17 x i8]* @.strCmpGeFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
 
   ; test fcmp::ogt -- should return true if neither operand is a NaN and the first is greater
   %cmp_gt    = fcmp ogt float %f1, %f2
   %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
-  %cmp_gt_em = getelementptr [17 x i8]* @.strCmpGtFlt, i32 0, i32 0
+  %cmp_gt_em = getelementptr [17 x i8], [17 x i8]* @.strCmpGtFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
 
   ; test fcmp::ole -- should return true if neither operand is a NaN and the first is less or equal
   %cmp_le    = fcmp ole float %f1, %f2
   %cmp_le_ok = icmp eq i1 %cmp_le, %le
-  %cmp_le_em = getelementptr [17 x i8]* @.strCmpLeFlt, i32 0, i32 0
+  %cmp_le_em = getelementptr [17 x i8], [17 x i8]* @.strCmpLeFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
 
   ; test fcmp::olt -- should return true if neither operand is a NaN and the first is less
   %cmp_lt    = fcmp olt float %f1, %f2
   %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
-  %cmp_lt_em = getelementptr [17 x i8]* @.strCmpLtFlt, i32 0, i32 0
+  %cmp_lt_em = getelementptr [17 x i8], [17 x i8]* @.strCmpLtFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
 
   ; test fcmp::one -- should return true if neither operand is a NaN and they are not equal
   %cmp_ne    = fcmp one float %f1, %f2
   %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
-  %cmp_ne_em = getelementptr [17 x i8]* @.strCmpNeFlt, i32 0, i32 0
+  %cmp_ne_em = getelementptr [17 x i8], [17 x i8]* @.strCmpNeFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
 
   ret void
@@ -440,55 +444,55 @@ entry:
   ; test fcmp::true -- should always return true
   %cmp_t    = fcmp true double %d1, %d2
   %cmp_t_ok = icmp eq i1 %cmp_t, 1
-  %cmp_t_em = getelementptr [19 x i8]* @.strCmpTrDbl, i32 0, i32 0
+  %cmp_t_em = getelementptr [19 x i8], [19 x i8]* @.strCmpTrDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_t_ok, i8* %cmp_t_em )
 
   ; test fcmp::false -- should always return false
   %cmp_f    = fcmp false double %d1, %d2
   %cmp_f_ok = icmp eq i1 %cmp_f, 0
-  %cmp_f_em = getelementptr [20 x i8]* @.strCmpFaDbl, i32 0, i32 0
+  %cmp_f_em = getelementptr [20 x i8], [20 x i8]* @.strCmpFaDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_f_ok, i8* %cmp_f_em )
 
   ; test fcmp::ord -- should return true if neither operand is NaN
   %cmp_o    = fcmp ord double %d1, %d2
   %cmp_o_ok = icmp eq i1 %cmp_o, %ord
-  %cmp_o_em = getelementptr [19 x i8]* @.strCmpOrdDbl, i32 0, i32 0
+  %cmp_o_em = getelementptr [19 x i8], [19 x i8]* @.strCmpOrdDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
 
   ; test fcmp::oeq -- should return true if neither operand is a NaN and they are equal
   %cmp_eq    = fcmp oeq double %d1, %d2
   %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
-  %cmp_eq_em = getelementptr [18 x i8]* @.strCmpEqDbl, i32 0, i32 0
+  %cmp_eq_em = getelementptr [18 x i8], [18 x i8]* @.strCmpEqDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
 
   ; test fcmp::oge -- should return true if neither operand is a NaN and the first is greater or equal
   %cmp_ge    = fcmp oge double %d1, %d2
   %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
-  %cmp_ge_em = getelementptr [18 x i8]* @.strCmpGeDbl, i32 0, i32 0
+  %cmp_ge_em = getelementptr [18 x i8], [18 x i8]* @.strCmpGeDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
 
   ; test fcmp::ogt -- should return true if neither operand is a NaN and the first is greater
   %cmp_gt    = fcmp ogt double %d1, %d2
   %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
-  %cmp_gt_em = getelementptr [18 x i8]* @.strCmpGtDbl, i32 0, i32 0
+  %cmp_gt_em = getelementptr [18 x i8], [18 x i8]* @.strCmpGtDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
 
   ; test fcmp::ole -- should return true if neither operand is a NaN and the first is less or equal
   %cmp_le    = fcmp ole double %d1, %d2
   %cmp_le_ok = icmp eq i1 %cmp_le, %le
-  %cmp_le_em = getelementptr [18 x i8]* @.strCmpLeDbl, i32 0, i32 0
+  %cmp_le_em = getelementptr [18 x i8], [18 x i8]* @.strCmpLeDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
 
   ; test fcmp::olt -- should return true if neither operand is a NaN and the first is less
   %cmp_lt    = fcmp olt double %d1, %d2
   %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
-  %cmp_lt_em = getelementptr [18 x i8]* @.strCmpLtDbl, i32 0, i32 0
+  %cmp_lt_em = getelementptr [18 x i8], [18 x i8]* @.strCmpLtDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
 
   ; test fcmp::one -- should return true if neither operand is a NaN and they are not equal
   %cmp_ne    = fcmp one double %d1, %d2
   %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
-  %cmp_ne_em = getelementptr [18 x i8]* @.strCmpNeDbl, i32 0, i32 0
+  %cmp_ne_em = getelementptr [18 x i8], [18 x i8]* @.strCmpNeDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
 
   ret void
@@ -512,43 +516,43 @@ entry:
   ; test fcmp::uno -- should return true if either operand is NaN
   %cmp_o    = fcmp uno float %f1, %f2
   %cmp_o_ok = icmp eq i1 %cmp_o, %uno
-  %cmp_o_em = getelementptr [20 x i8]* @.strCmpUnoFlt, i32 0, i32 0
+  %cmp_o_em = getelementptr [20 x i8], [20 x i8]* @.strCmpUnoFlt, i32 0, i32 0
   call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
 
   ; test fcmp::oeq -- should return true if either operand is a NaN and they are equal
   %cmp_eq    = fcmp ueq float %f1, %f2
   %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
-  %cmp_eq_em = getelementptr [17 x i8]* @.strCmpEqFltU, i32 0, i32 0
+  %cmp_eq_em = getelementptr [17 x i8], [17 x i8]* @.strCmpEqFltU, i32 0, i32 0
   call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
 
   ; test fcmp::oge -- should return true if either operand is a NaN and the first is greater or equal
   %cmp_ge    = fcmp uge float %f1, %f2
   %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
-  %cmp_ge_em = getelementptr [17 x i8]* @.strCmpGeFltU, i32 0, i32 0
+  %cmp_ge_em = getelementptr [17 x i8], [17 x i8]* @.strCmpGeFltU, i32 0, i32 0
   call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
 
   ; test fcmp::ogt -- should return true if either operand is a NaN and the first is greater
   %cmp_gt    = fcmp ugt float %f1, %f2
   %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
-  %cmp_gt_em = getelementptr [17 x i8]* @.strCmpGtFltU, i32 0, i32 0
+  %cmp_gt_em = getelementptr [17 x i8], [17 x i8]* @.strCmpGtFltU, i32 0, i32 0
   call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
 
   ; test fcmp::ole -- should return true if either operand is a NaN and the first is less or equal
   %cmp_le    = fcmp ule float %f1, %f2
   %cmp_le_ok = icmp eq i1 %cmp_le, %le
-  %cmp_le_em = getelementptr [17 x i8]* @.strCmpLeFltU, i32 0, i32 0
+  %cmp_le_em = getelementptr [17 x i8], [17 x i8]* @.strCmpLeFltU, i32 0, i32 0
   call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
 
   ; test fcmp::olt -- should return true if either operand is a NaN and the first is less
   %cmp_lt    = fcmp ult float %f1, %f2
   %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
-  %cmp_lt_em = getelementptr [17 x i8]* @.strCmpLtFltU, i32 0, i32 0
+  %cmp_lt_em = getelementptr [17 x i8], [17 x i8]* @.strCmpLtFltU, i32 0, i32 0
   call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
 
   ; test fcmp::one -- should return true if either operand is a NaN and they are not equal
   %cmp_ne    = fcmp une float %f1, %f2
   %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
-  %cmp_ne_em = getelementptr [17 x i8]* @.strCmpNeFltU, i32 0, i32 0
+  %cmp_ne_em = getelementptr [17 x i8], [17 x i8]* @.strCmpNeFltU, i32 0, i32 0
   call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
 
   ret void
@@ -560,43 +564,43 @@ entry:
   ; test fcmp::uno -- should return true if either operand is NaN
   %cmp_o    = fcmp uno double %d1, %d2
   %cmp_o_ok = icmp eq i1 %cmp_o, %uno
-  %cmp_o_em = getelementptr [21 x i8]* @.strCmpUnoDbl, i32 0, i32 0
+  %cmp_o_em = getelementptr [21 x i8], [21 x i8]* @.strCmpUnoDbl, i32 0, i32 0
   call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
 
   ; test fcmp::ueq -- should return true if either operand is a NaN and they are equal
   %cmp_eq    = fcmp ueq double %d1, %d2
   %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
-  %cmp_eq_em = getelementptr [18 x i8]* @.strCmpEqDblU, i32 0, i32 0
+  %cmp_eq_em = getelementptr [18 x i8], [18 x i8]* @.strCmpEqDblU, i32 0, i32 0
   call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
 
   ; test fcmp::uge -- should return true if either operand is a NaN and the first is greater or equal
   %cmp_ge    = fcmp uge double %d1, %d2
   %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
-  %cmp_ge_em = getelementptr [18 x i8]* @.strCmpGeDblU, i32 0, i32 0
+  %cmp_ge_em = getelementptr [18 x i8], [18 x i8]* @.strCmpGeDblU, i32 0, i32 0
   call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
 
   ; test fcmp::ugt -- should return true if either operand is a NaN and the first is greater
   %cmp_gt    = fcmp ugt double %d1, %d2
   %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
-  %cmp_gt_em = getelementptr [18 x i8]* @.strCmpGtDblU, i32 0, i32 0
+  %cmp_gt_em = getelementptr [18 x i8], [18 x i8]* @.strCmpGtDblU, i32 0, i32 0
   call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
 
   ; test fcmp::ule -- should return true if either operand is a NaN and the first is less or equal
   %cmp_le    = fcmp ule double %d1, %d2
   %cmp_le_ok = icmp eq i1 %cmp_le, %le
-  %cmp_le_em = getelementptr [18 x i8]* @.strCmpLeDblU, i32 0, i32 0
+  %cmp_le_em = getelementptr [18 x i8], [18 x i8]* @.strCmpLeDblU, i32 0, i32 0
   call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
 
   ; test fcmp::ult -- should return true if either operand is a NaN and the first is less
   %cmp_lt    = fcmp ult double %d1, %d2
   %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
-  %cmp_lt_em = getelementptr [18 x i8]* @.strCmpLtDblU, i32 0, i32 0
+  %cmp_lt_em = getelementptr [18 x i8], [18 x i8]* @.strCmpLtDblU, i32 0, i32 0
   call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
 
   ; test fcmp::une -- should return true if either operand is a NaN and they are not equal
   %cmp_ne    = fcmp une double %d1, %d2
   %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
-  %cmp_ne_em = getelementptr [18 x i8]* @.strCmpNeDblU, i32 0, i32 0
+  %cmp_ne_em = getelementptr [18 x i8], [18 x i8]* @.strCmpNeDblU, i32 0, i32 0
   call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
 
   ret void
@@ -639,8 +643,8 @@ entry:
   store i64 -1, i64* %nan_as_i64
 
   ; load two copies of our NaN
-  %nan1 = load double* %nan
-  %nan2 = load double* %nan
+  %nan1 = load double, double* %nan
+  %nan2 = load double, double* %nan
 
   ; NaNs do different things depending on ordered vs unordered
   call void @testFCmpBothOrdered( double %nan1, double 0.000000e+00, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0 )
@@ -670,8 +674,8 @@ entry:
   call void @testFCmp( )
 
   ; everything worked -- print a message saying so
-  %works_msg = getelementptr [20 x i8]* @.strWorks, i32 0, i32 0
-  %ret = call i32 (i8*, ...)* @printf( i8* %works_msg )
+  %works_msg = getelementptr [20 x i8], [20 x i8]* @.strWorks, i32 0, i32 0
+  %ret = call i32 (i8*, ...) @printf( i8* %works_msg )
 
   ret i32 0
 }
diff --git a/test/Concrete/GlobalInitializers.leq36.ll b/test/Concrete/GlobalInitializers.leq36.ll
new file mode 100755
index 00000000..ba7e53eb
--- /dev/null
+++ b/test/Concrete/GlobalInitializers.leq36.ll
@@ -0,0 +1,48 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
+
+declare void @print_i32(i32)
+
+%simple = type { i8, i16, i32, i64 }
+@gInt = global i32 2
+@gInts = global [2 x i32] [ i32 3, i32 5 ]
+@gStruct = global %simple { i8 7, i16 11, i32 13, i64 17 }
+@gZero = global %simple zeroinitializer
+
+define i32 @main() {
+entry:
+	%addr0 = getelementptr i32* @gInt, i32 0
+	%addr1 = getelementptr [2 x i32]* @gInts, i32 0, i32 0
+	%addr2 = getelementptr [2 x i32]* @gInts, i32 0, i32 1
+	%addr3 = getelementptr %simple* @gStruct, i32 0, i32 0
+	%addr4 = getelementptr %simple* @gStruct, i32 0, i32 1
+	%addr5 = getelementptr %simple* @gStruct, i32 0, i32 2
+	%addr6 = getelementptr %simple* @gStruct, i32 0, i32 3
+	%addr7 = getelementptr %simple* @gZero, i32 0, i32 2
+	%contents0 = load i32* %addr0
+	%contents1 = load i32* %addr1
+	%contents2 = load i32* %addr2
+	%contents3tmp = load i8* %addr3
+	%contents3 = zext i8 %contents3tmp to i32
+	%contents4tmp = load i16* %addr4
+	%contents4 = zext i16 %contents4tmp to i32
+	%contents5 = load i32* %addr5
+	%contents6tmp = load i64* %addr6
+	%contents6 = trunc i64 %contents6tmp to i32
+	%contents7 = load i32* %addr7
+	%tmp0 = mul i32 %contents0, %contents1
+	%tmp1 = mul i32 %tmp0, %contents2
+	%tmp2 = mul i32 %tmp1, %contents3
+	%tmp3 = mul i32 %tmp2, %contents4
+	%tmp4 = mul i32 %tmp3, %contents5
+	%tmp5 = mul i32 %tmp4, %contents6
+	%tmp6 = add i32 %tmp5, %contents7
+	%p = icmp eq i32 %tmp5, 510510
+	br i1 %p, label %exitTrue, label %exitFalse
+exitTrue:
+	call void @print_i32(i32 1)
+	ret i32 0
+exitFalse:
+	call void @print_i32(i32 0)
+	ret i32 0
+}
diff --git a/test/Concrete/GlobalInitializers.ll b/test/Concrete/GlobalInitializers.ll
index e3657dad..57e702dc 100755
--- a/test/Concrete/GlobalInitializers.ll
+++ b/test/Concrete/GlobalInitializers.ll
@@ -1,3 +1,6 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; LLVM 3.7 requires a type as the first argument to 'load'
+; REQUIRES: geq-llvm-3.7
 ; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
 
 declare void @print_i32(i32)
@@ -10,25 +13,25 @@ declare void @print_i32(i32)
 
 define i32 @main() {
 entry:
-	%addr0 = getelementptr i32* @gInt, i32 0
-	%addr1 = getelementptr [2 x i32]* @gInts, i32 0, i32 0
-	%addr2 = getelementptr [2 x i32]* @gInts, i32 0, i32 1
-	%addr3 = getelementptr %simple* @gStruct, i32 0, i32 0
-	%addr4 = getelementptr %simple* @gStruct, i32 0, i32 1
-	%addr5 = getelementptr %simple* @gStruct, i32 0, i32 2
-	%addr6 = getelementptr %simple* @gStruct, i32 0, i32 3
-	%addr7 = getelementptr %simple* @gZero, i32 0, i32 2
-	%contents0 = load i32* %addr0
-	%contents1 = load i32* %addr1
-	%contents2 = load i32* %addr2
-	%contents3tmp = load i8* %addr3
+	%addr0 = getelementptr i32, i32* @gInt, i32 0
+	%addr1 = getelementptr [2 x i32], [2 x i32]* @gInts, i32 0, i32 0
+	%addr2 = getelementptr [2 x i32], [2 x i32]* @gInts, i32 0, i32 1
+	%addr3 = getelementptr %simple, %simple* @gStruct, i32 0, i32 0
+	%addr4 = getelementptr %simple, %simple* @gStruct, i32 0, i32 1
+	%addr5 = getelementptr %simple, %simple* @gStruct, i32 0, i32 2
+	%addr6 = getelementptr %simple, %simple* @gStruct, i32 0, i32 3
+	%addr7 = getelementptr %simple, %simple* @gZero, i32 0, i32 2
+	%contents0 = load i32, i32* %addr0
+	%contents1 = load i32, i32* %addr1
+	%contents2 = load i32, i32* %addr2
+	%contents3tmp = load i8, i8* %addr3
 	%contents3 = zext i8 %contents3tmp to i32
-	%contents4tmp = load i16* %addr4
+	%contents4tmp = load i16, i16* %addr4
 	%contents4 = zext i16 %contents4tmp to i32
-	%contents5 = load i32* %addr5
-	%contents6tmp = load i64* %addr6
+	%contents5 = load i32, i32* %addr5
+	%contents6tmp = load i64, i64* %addr6
 	%contents6 = trunc i64 %contents6tmp to i32
-	%contents7 = load i32* %addr7
+	%contents7 = load i32, i32* %addr7
 	%tmp0 = mul i32 %contents0, %contents1
 	%tmp1 = mul i32 %tmp0, %contents2
 	%tmp2 = mul i32 %tmp1, %contents3
diff --git a/test/Concrete/SimpleStoreAndLoad.leq36.ll b/test/Concrete/SimpleStoreAndLoad.leq36.ll
new file mode 100644
index 00000000..7bb65ea7
--- /dev/null
+++ b/test/Concrete/SimpleStoreAndLoad.leq36.ll
@@ -0,0 +1,20 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
+
+declare void @print_i32(i32)
+
+define i32 @main() {
+entry:
+	%a = alloca i32, i32 4
+	%tmp1 = getelementptr i32* %a, i32 0
+	store i32 0, i32* %tmp1
+	%tmp2 = load i32* %tmp1
+	%tmp3 = icmp eq i32 %tmp2, 0
+	br i1 %tmp3, label %exitTrue, label %exitFalse
+exitTrue:
+	call void @print_i32(i32 1)
+	ret i32 0
+exitFalse:
+	call void @print_i32(i32 0)
+	ret i32 0
+}
diff --git a/test/Concrete/SimpleStoreAndLoad.ll b/test/Concrete/SimpleStoreAndLoad.ll
index 1edad038..951a474e 100644
--- a/test/Concrete/SimpleStoreAndLoad.ll
+++ b/test/Concrete/SimpleStoreAndLoad.ll
@@ -1,3 +1,6 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; LLVM 3.7 requires a type as the first argument to 'load'
+; REQUIRES: geq-llvm-3.7
 ; RUN: %S/ConcreteTest.py --klee='%klee' --lli=%lli %s
 
 declare void @print_i32(i32)
@@ -5,9 +8,9 @@ declare void @print_i32(i32)
 define i32 @main() {
 entry:
 	%a = alloca i32, i32 4
-	%tmp1 = getelementptr i32* %a, i32 0
+	%tmp1 = getelementptr i32, i32* %a, i32 0
 	store i32 0, i32* %tmp1
-	%tmp2 = load i32* %tmp1
+	%tmp2 = load i32, i32* %tmp1
 	%tmp3 = icmp eq i32 %tmp2, 0
 	br i1 %tmp3, label %exitTrue, label %exitFalse
 exitTrue:
diff --git a/test/Feature/BitcastAlias.leq36.ll b/test/Feature/BitcastAlias.leq36.ll
new file mode 100644
index 00000000..d203e52c
--- /dev/null
+++ b/test/Feature/BitcastAlias.leq36.ll
@@ -0,0 +1,35 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: llvm-as %s -f -o %t1.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
+; RUN: grep PASS %t2
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@foo = alias i32 (i32)* @__foo
+
+define i32 @__foo(i32 %i) nounwind {
+entry:
+  ret i32 %i
+}
+
+declare i32 @puts(i8*)
+
+@.passstr = private constant [5 x i8] c"PASS\00", align 1
+@.failstr = private constant [5 x i8] c"FAIL\00", align 1
+
+define i32 @main(i32 %argc, i8** nocapture %argv) nounwind readnone {
+entry:
+  %call = call i32 (i64)* bitcast (i32 (i32)* @foo to i32 (i64)*)(i64 52)
+  %r = icmp eq i32 %call, 52
+  br i1 %r, label %bbtrue, label %bbfalse
+
+bbtrue:
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  ret i32 0
+
+bbfalse:
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  ret i32 0
+}
diff --git a/test/Feature/BitcastAlias.ll b/test/Feature/BitcastAlias.ll
index e0e3653f..5bd30193 100644
--- a/test/Feature/BitcastAlias.ll
+++ b/test/Feature/BitcastAlias.ll
@@ -1,3 +1,6 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; LLVM 3.7 no longer accepts '*' with a 'call'
+; REQUIRES: geq-llvm-3.7
 ; RUN: llvm-as %s -f -o %t1.bc
 ; RUN: rm -rf %t.klee-out
 ; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
@@ -20,15 +23,15 @@ declare i32 @puts(i8*)
 
 define i32 @main(i32 %argc, i8** nocapture %argv) nounwind readnone {
 entry:
-  %call = call i32 (i64)* bitcast (i32 (i32)* @foo to i32 (i64)*)(i64 52)
+  %call = call i32 (i64) bitcast (i32 (i32)* @foo to i32 (i64)*)(i64 52)
   %r = icmp eq i32 %call, 52
   br i1 %r, label %bbtrue, label %bbfalse
 
 bbtrue:
-  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.passstr, i64 0, i64 0)) nounwind
   ret i32 0
 
 bbfalse:
-  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.failstr, i64 0, i64 0)) nounwind
   ret i32 0
 }
diff --git a/test/Feature/BitcastAliasMD2U.leq36.ll b/test/Feature/BitcastAliasMD2U.leq36.ll
new file mode 100644
index 00000000..cef8ac54
--- /dev/null
+++ b/test/Feature/BitcastAliasMD2U.leq36.ll
@@ -0,0 +1,35 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: llvm-as %s -f -o %t1.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee --output-dir=%t.klee-out -disable-opt -search=nurs:md2u %t1.bc > %t2
+; RUN: grep PASS %t2
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@foo = alias i32 (i32)* @__foo
+
+define i32 @__foo(i32 %i) nounwind {
+entry:
+  ret i32 %i
+}
+
+declare i32 @puts(i8*)
+
+@.passstr = private constant [5 x i8] c"PASS\00", align 1
+@.failstr = private constant [5 x i8] c"FAIL\00", align 1
+
+define i32 @main(i32 %argc, i8** nocapture %argv) nounwind readnone {
+entry:
+  %call = call i32 (i64)* bitcast (i32 (i32)* @foo to i32 (i64)*)(i64 52)
+  %r = icmp eq i32 %call, 52
+  br i1 %r, label %bbtrue, label %bbfalse
+
+bbtrue:
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  ret i32 0
+
+bbfalse:
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  ret i32 0
+}
diff --git a/test/Feature/BitcastAliasMD2U.ll b/test/Feature/BitcastAliasMD2U.ll
index 24eabaa5..7eddd3d6 100644
--- a/test/Feature/BitcastAliasMD2U.ll
+++ b/test/Feature/BitcastAliasMD2U.ll
@@ -1,3 +1,6 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; LLVM 3.7 no longer accepts '*' with a 'call'
+; REQUIRES: geq-llvm-3.7
 ; RUN: llvm-as %s -f -o %t1.bc
 ; RUN: rm -rf %t.klee-out
 ; RUN: %klee --output-dir=%t.klee-out -disable-opt -search=nurs:md2u %t1.bc > %t2
@@ -20,15 +23,15 @@ declare i32 @puts(i8*)
 
 define i32 @main(i32 %argc, i8** nocapture %argv) nounwind readnone {
 entry:
-  %call = call i32 (i64)* bitcast (i32 (i32)* @foo to i32 (i64)*)(i64 52)
+  %call = call i32 (i64) bitcast (i32 (i32)* @foo to i32 (i64)*)(i64 52)
   %r = icmp eq i32 %call, 52
   br i1 %r, label %bbtrue, label %bbfalse
 
 bbtrue:
-  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.passstr, i64 0, i64 0)) nounwind
   ret i32 0
 
 bbfalse:
-  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.failstr, i64 0, i64 0)) nounwind
   ret i32 0
 }
diff --git a/test/Feature/ConstantArray.leq36.ll b/test/Feature/ConstantArray.leq36.ll
new file mode 100644
index 00000000..a4986ff4
--- /dev/null
+++ b/test/Feature/ConstantArray.leq36.ll
@@ -0,0 +1,52 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: llvm-as %s -f -o %t1.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc 2>&1 | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@.str = private unnamed_addr constant [2 x i8] c"0\00", align 1
+@.str2 = private unnamed_addr constant [2 x i8] c"1\00", align 1
+
+%struct.dirent = type { i32, i32, i16, i8 }
+declare void @klee_print_expr(i8*, ...)
+
+define i32 @main() {
+entry:
+	%a = alloca %struct.dirent
+	%tmp1 = getelementptr %struct.dirent* %a, i32 0
+	%tmp2 = bitcast %struct.dirent* %tmp1 to <2 x i32>*
+	; Initialize with constant vector
+	store <2 x i32> <i32 42, i32 4096>, <2 x i32>* %tmp2
+	br label %exit
+exit:
+	; Print first initialized element
+	%idx = getelementptr %struct.dirent* %a, i32 0, i32 0
+	%val = load i32* %idx
+	call void(i8*, ...)* @klee_print_expr(i8* getelementptr inbounds ([2 x i8]* @.str, i32 0, i32 0), i32 %val)
+	; CHECK: 0:42
+
+	; Print second initialized element
+	%idx2 = getelementptr %struct.dirent* %a, i32 0, i32 1
+	%val2 = load i32* %idx2
+	call void(i8*, ...)* @klee_print_expr(i8* getelementptr inbounds ([2 x i8]* @.str2, i32 0, i32 0), i32 %val2)
+	; CHECK: 1:4096
+	
+	; Initialize with constant array
+	%array = alloca [2 x i32];
+	store [2 x i32][i32 7, i32 9], [2 x i32]* %array
+
+	; Print first initialized element
+	%idx3 = getelementptr [2 x i32]* %array, i32 0, i32 0
+	%val3 = load i32* %idx3
+	call void(i8*, ...)* @klee_print_expr(i8* getelementptr inbounds ([2 x i8]* @.str, i32 0, i32 0), i32 %val3)
+	; CHECK: 0:7
+
+	; Print second initialized element
+	%idx4 = getelementptr [2 x i32]* %array, i32 0, i32 1
+	%val4 = load i32* %idx4
+	call void(i8*, ...)* @klee_print_expr(i8* getelementptr inbounds ([2 x i8]* @.str2, i32 0, i32 0), i32 %val4)
+	; CHECK: 1:9
+	
+	ret i32 0
+}
diff --git a/test/Feature/ConstantArray.ll b/test/Feature/ConstantArray.ll
index 161b2a16..195b4cb0 100644
--- a/test/Feature/ConstantArray.ll
+++ b/test/Feature/ConstantArray.ll
@@ -1,3 +1,7 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; LLVM 3.7 requires a type as the first argument to 'load'
+; LLVM 3.7 no longer accepts '*' with a 'call'
+; REQUIRES: geq-llvm-3.7
 ; RUN: llvm-as %s -f -o %t1.bc
 ; RUN: rm -rf %t.klee-out
 ; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc 2>&1 | FileCheck %s
@@ -13,22 +17,22 @@ declare void @klee_print_expr(i8*, ...)
 define i32 @main() {
 entry:
 	%a = alloca %struct.dirent
-	%tmp1 = getelementptr %struct.dirent* %a, i32 0
+	%tmp1 = getelementptr %struct.dirent, %struct.dirent* %a, i32 0
 	%tmp2 = bitcast %struct.dirent* %tmp1 to <2 x i32>*
 	; Initialize with constant vector
 	store <2 x i32> <i32 42, i32 4096>, <2 x i32>* %tmp2
 	br label %exit
 exit:
 	; Print first initialized element
-	%idx = getelementptr %struct.dirent* %a, i32 0, i32 0
-	%val = load i32* %idx
-	call void(i8*, ...)* @klee_print_expr(i8* getelementptr inbounds ([2 x i8]* @.str, i32 0, i32 0), i32 %val)
+	%idx = getelementptr %struct.dirent, %struct.dirent* %a, i32 0, i32 0
+	%val = load i32, i32* %idx
+	call void(i8*, ...) @klee_print_expr(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0), i32 %val)
 	; CHECK: 0:42
 
 	; Print second initialized element
-	%idx2 = getelementptr %struct.dirent* %a, i32 0, i32 1
-	%val2 = load i32* %idx2
-	call void(i8*, ...)* @klee_print_expr(i8* getelementptr inbounds ([2 x i8]* @.str2, i32 0, i32 0), i32 %val2)
+	%idx2 = getelementptr %struct.dirent, %struct.dirent* %a, i32 0, i32 1
+	%val2 = load i32, i32* %idx2
+	call void(i8*, ...) @klee_print_expr(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str2, i32 0, i32 0), i32 %val2)
 	; CHECK: 1:4096
 	
 	; Initialize with constant array
@@ -36,16 +40,16 @@ exit:
 	store [2 x i32][i32 7, i32 9], [2 x i32]* %array
 
 	; Print first initialized element
-	%idx3 = getelementptr [2 x i32]* %array, i32 0, i32 0
-	%val3 = load i32* %idx3
-	call void(i8*, ...)* @klee_print_expr(i8* getelementptr inbounds ([2 x i8]* @.str, i32 0, i32 0), i32 %val3)
+	%idx3 = getelementptr [2 x i32], [2 x i32]* %array, i32 0, i32 0
+	%val3 = load i32, i32* %idx3
+	call void(i8*, ...) @klee_print_expr(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0), i32 %val3)
 	; CHECK: 0:7
 
 	; Print second initialized element
-	%idx4 = getelementptr [2 x i32]* %array, i32 0, i32 1
-	%val4 = load i32* %idx4
-	call void(i8*, ...)* @klee_print_expr(i8* getelementptr inbounds ([2 x i8]* @.str2, i32 0, i32 0), i32 %val4)
+	%idx4 = getelementptr [2 x i32], [2 x i32]* %array, i32 0, i32 1
+	%val4 = load i32, i32* %idx4
+	call void(i8*, ...) @klee_print_expr(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str2, i32 0, i32 0), i32 %val4)
 	; CHECK: 1:9
 	
 	ret i32 0
-}
\ No newline at end of file
+}
diff --git a/test/Feature/ConstantStruct.leq36.ll b/test/Feature/ConstantStruct.leq36.ll
new file mode 100644
index 00000000..073544d3
--- /dev/null
+++ b/test/Feature/ConstantStruct.leq36.ll
@@ -0,0 +1,34 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: llvm-as %s -f -o %t1.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
+; RUN: grep PASS %t2
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.sfoo = type { i32, i64 }
+
+declare i32 @puts(i8*)
+declare i32 @printf(i8*, ...)
+
+@.passstr = private constant [5 x i8] c"PASS\00", align 1
+@.failstr = private constant [5 x i8] c"FAIL\00", align 1
+
+define i32 @main(i32 %argc, i8** nocapture %argv) nounwind readnone {
+entry:
+  %f0 = extractvalue %struct.sfoo { i32 3, i64 1 }, 0
+  %f1 = extractvalue %struct.sfoo { i32 3, i64 1 }, 1
+  %xf0 = zext i32 %f0 to i64
+  %f0mf1 = sub i64 %xf0, %f1
+  %r = icmp eq i64 %f0mf1, 2
+  br i1 %r, label %bbtrue, label %bbfalse
+
+bbtrue:
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  ret i32 0
+
+bbfalse:
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  ret i32 0
+}
diff --git a/test/Feature/ConstantStruct.ll b/test/Feature/ConstantStruct.ll
index 4fe6b5d0..e4b3d07b 100644
--- a/test/Feature/ConstantStruct.ll
+++ b/test/Feature/ConstantStruct.ll
@@ -1,3 +1,5 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; REQUIRES: geq-llvm-3.7
 ; RUN: llvm-as %s -f -o %t1.bc
 ; RUN: rm -rf %t.klee-out
 ; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
@@ -24,10 +26,10 @@ entry:
   br i1 %r, label %bbtrue, label %bbfalse
 
 bbtrue:
-  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.passstr, i64 0, i64 0)) nounwind
   ret i32 0
 
 bbfalse:
-  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.failstr, i64 0, i64 0)) nounwind
   ret i32 0
 }
diff --git a/test/Feature/GetElementPtr.leq36.ll b/test/Feature/GetElementPtr.leq36.ll
new file mode 100644
index 00000000..43f33e27
--- /dev/null
+++ b/test/Feature/GetElementPtr.leq36.ll
@@ -0,0 +1,30 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: llvm-as %s -f -o %t1.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
+; RUN: grep PASS %t2
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i32 @puts(i8*)
+
+@.passstr = private constant [5 x i8] c"PASS\00", align 1
+@.failstr = private constant [5 x i8] c"FAIL\00", align 1
+
+define i32 @main() {
+entry:
+  %addr = alloca i8, align 4
+  %addrp1 = getelementptr i8* %addr, i32 1
+  %addrp1m1 = getelementptr i8* %addrp1, i32 -1
+  %test = icmp eq i8* %addr, %addrp1m1
+  br i1 %test, label %bbtrue, label %bbfalse
+
+bbtrue:
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  ret i32 0
+
+bbfalse:
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  ret i32 0
+}
diff --git a/test/Feature/GetElementPtr.ll b/test/Feature/GetElementPtr.ll
index da94441c..f7f8aada 100644
--- a/test/Feature/GetElementPtr.ll
+++ b/test/Feature/GetElementPtr.ll
@@ -1,3 +1,5 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; REQUIRES: geq-llvm-3.7
 ; RUN: llvm-as %s -f -o %t1.bc
 ; RUN: rm -rf %t.klee-out
 ; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
@@ -14,16 +16,16 @@ declare i32 @puts(i8*)
 define i32 @main() {
 entry:
   %addr = alloca i8, align 4
-  %addrp1 = getelementptr i8* %addr, i32 1
-  %addrp1m1 = getelementptr i8* %addrp1, i32 -1
+  %addrp1 = getelementptr i8, i8* %addr, i32 1
+  %addrp1m1 = getelementptr i8, i8* %addrp1, i32 -1
   %test = icmp eq i8* %addr, %addrp1m1
   br i1 %test, label %bbtrue, label %bbfalse
 
 bbtrue:
-  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.passstr, i64 0, i64 0)) nounwind
   ret i32 0
 
 bbfalse:
-  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.failstr, i64 0, i64 0)) nounwind
   ret i32 0
 }
diff --git a/test/Feature/InsertExtractValue.leq36.ll b/test/Feature/InsertExtractValue.leq36.ll
new file mode 100644
index 00000000..431e14c4
--- /dev/null
+++ b/test/Feature/InsertExtractValue.leq36.ll
@@ -0,0 +1,34 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: llvm-as %s -f -o %t1.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
+; RUN: grep PASS %t2
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.sfoo = type { i32, i32 }
+
+declare i32 @puts(i8*)
+
+@.passstr = private constant [5 x i8] c"PASS\00", align 1
+@.failstr = private constant [5 x i8] c"FAIL\00", align 1
+
+define i32 @main(i32 %argc, i8** nocapture %argv) nounwind readnone {
+entry:
+  %s0 = insertvalue %struct.sfoo undef, i32 3, 0
+  %s1 = insertvalue %struct.sfoo %s0, i32 1, 1
+  %f0 = extractvalue %struct.sfoo %s1, 0
+  %f1 = extractvalue %struct.sfoo %s1, 1
+  %f0mf1 = sub i32 %f0, %f1
+  %r = icmp eq i32 %f0mf1, 2
+  br i1 %r, label %bbtrue, label %bbfalse
+
+bbtrue:
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  ret i32 0
+
+bbfalse:
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  ret i32 0
+}
diff --git a/test/Feature/InsertExtractValue.ll b/test/Feature/InsertExtractValue.ll
index 83e8f851..fff6da7c 100644
--- a/test/Feature/InsertExtractValue.ll
+++ b/test/Feature/InsertExtractValue.ll
@@ -1,3 +1,5 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; REQUIRES: geq-llvm-3.7
 ; RUN: llvm-as %s -f -o %t1.bc
 ; RUN: rm -rf %t.klee-out
 ; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
@@ -24,10 +26,10 @@ entry:
   br i1 %r, label %bbtrue, label %bbfalse
 
 bbtrue:
-  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.passstr, i64 0, i64 0)) nounwind
   ret i32 0
 
 bbfalse:
-  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.failstr, i64 0, i64 0)) nounwind
   ret i32 0
 }
diff --git a/test/Feature/Overflow.leq36.ll b/test/Feature/Overflow.leq36.ll
new file mode 100644
index 00000000..2ab04772
--- /dev/null
+++ b/test/Feature/Overflow.leq36.ll
@@ -0,0 +1,45 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: llvm-as %s -f -o %t1.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
+; RUN: grep PASS %t2
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b)
+
+declare i32 @puts(i8*)
+
+@.passstr = private constant [5 x i8] c"PASS\00", align 1
+@.failstr = private constant [5 x i8] c"FAIL\00", align 1
+
+define i32 @main() {
+bb0:
+  %s0 = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 0, i8 -1)
+  %v0 = extractvalue {i8, i1} %s0, 0
+  %c0 = icmp eq i8 %v0, -1
+  br i1 %c0, label %bb0_1, label %bbfalse
+
+bb0_1:
+  %o0 = extractvalue {i8, i1} %s0, 1
+  br i1 %o0, label %bbfalse, label %bb1
+
+bb1:
+  %s1 = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 1, i8 -1)
+  %v1 = extractvalue {i8, i1} %s1, 0
+  %c1 = icmp eq i8 %v1, 0
+  br i1 %c1, label %bb1_1, label %bbfalse
+
+bb1_1:
+  %o1 = extractvalue {i8, i1} %s1, 1
+  br i1 %o1, label %bbtrue, label %bbfalse
+  
+bbtrue:
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  ret i32 0
+
+bbfalse:
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  ret i32 0
+}
diff --git a/test/Feature/Overflow.ll b/test/Feature/Overflow.ll
index 35dfbd10..1dbe1216 100644
--- a/test/Feature/Overflow.ll
+++ b/test/Feature/Overflow.ll
@@ -1,3 +1,5 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; REQUIRES: geq-llvm-3.7
 ; RUN: llvm-as %s -f -o %t1.bc
 ; RUN: rm -rf %t.klee-out
 ; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
@@ -35,10 +37,10 @@ bb1_1:
   br i1 %o1, label %bbtrue, label %bbfalse
   
 bbtrue:
-  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.passstr, i64 0, i64 0)) nounwind
   ret i32 0
 
 bbfalse:
-  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.failstr, i64 0, i64 0)) nounwind
   ret i32 0
 }
diff --git a/test/Feature/OverflowMul.leq36.ll b/test/Feature/OverflowMul.leq36.ll
new file mode 100644
index 00000000..1b14d380
--- /dev/null
+++ b/test/Feature/OverflowMul.leq36.ll
@@ -0,0 +1,45 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: llvm-as %s -f -o %t1.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
+; RUN: grep PASS %t2
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare {i8, i1} @llvm.umul.with.overflow.i8(i8 %a, i8 %b)
+
+declare i32 @puts(i8*)
+
+@.passstr = private constant [5 x i8] c"PASS\00", align 1
+@.failstr = private constant [5 x i8] c"FAIL\00", align 1
+
+define i32 @main() {
+bb0:
+  %s0 = call {i8, i1} @llvm.umul.with.overflow.i8(i8 1, i8 128)
+  %v0 = extractvalue {i8, i1} %s0, 0
+  %c0 = icmp eq i8 %v0, 128
+  br i1 %c0, label %bb0_1, label %bbfalse
+
+bb0_1:
+  %o0 = extractvalue {i8, i1} %s0, 1
+  br i1 %o0, label %bbfalse, label %bb1
+
+bb1:
+  %s1 = call {i8, i1} @llvm.umul.with.overflow.i8(i8 2, i8 128)
+  %v1 = extractvalue {i8, i1} %s1, 0
+  %c1 = icmp eq i8 %v1, 0
+  br i1 %c1, label %bb1_1, label %bbfalse
+
+bb1_1:
+  %o1 = extractvalue {i8, i1} %s1, 1
+  br i1 %o1, label %bbtrue, label %bbfalse
+  
+bbtrue:
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  ret i32 0
+
+bbfalse:
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  ret i32 0
+}
diff --git a/test/Feature/OverflowMul.ll b/test/Feature/OverflowMul.ll
index 7026aa74..3173e43c 100644
--- a/test/Feature/OverflowMul.ll
+++ b/test/Feature/OverflowMul.ll
@@ -1,3 +1,5 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; REQUIRES: geq-llvm-3.7
 ; RUN: llvm-as %s -f -o %t1.bc
 ; RUN: rm -rf %t.klee-out
 ; RUN: %klee --output-dir=%t.klee-out -disable-opt %t1.bc > %t2
@@ -35,10 +37,10 @@ bb1_1:
   br i1 %o1, label %bbtrue, label %bbfalse
   
 bbtrue:
-  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.passstr, i64 0, i64 0)) nounwind
+  %0 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.passstr, i64 0, i64 0)) nounwind
   ret i32 0
 
 bbfalse:
-  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8]* @.failstr, i64 0, i64 0)) nounwind
+  %1 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.failstr, i64 0, i64 0)) nounwind
   ret i32 0
 }
diff --git a/test/Feature/_utils._ll b/test/Feature/_utils._ll
index 32a73bb1..d825df3a 100644
--- a/test/Feature/_utils._ll
+++ b/test/Feature/_utils._ll
@@ -1,3 +1,6 @@
+; LLVM 3.7 requires a type as the first argument to 'getelementptr'
+; LLVM 3.7 requires a type as the first argument to 'load'
+
 define i32 @util_make_and_i1(i32 %a, i32 %b) {
         %a_i1 = icmp ne i32 %a, 0
         %b_i1 = icmp ne i32 %b, 0
@@ -17,26 +20,26 @@ define i32 @util_make_or_i1(i32 %a, i32 %b) {
 define i16 @util_make_concat2(i8 %a, i8 %b) {
         %tmp = alloca i16
         %tmp8 = bitcast i16* %tmp to i8*
-        %p0 = getelementptr i8* %tmp8, i32 0
-        %p1 = getelementptr i8* %tmp8, i32 1
+        %p0 = getelementptr i8, i8* %tmp8, i32 0
+        %p1 = getelementptr i8, i8* %tmp8, i32 1
         store i8 %b, i8* %p0
         store i8 %a, i8* %p1
-        %concat = load i16* %tmp
+        %concat = load i16, i16* %tmp
         ret i16 %concat
 }
 
 define i32 @util_make_concat4(i8 %a, i8 %b, i8 %c, i8 %d) {
         %tmp = alloca i32
         %tmp8 = bitcast i32* %tmp to i8*
-        %p0 = getelementptr i8* %tmp8, i32 0
-        %p1 = getelementptr i8* %tmp8, i32 1
-        %p2 = getelementptr i8* %tmp8, i32 2
-        %p3 = getelementptr i8* %tmp8, i32 3
+        %p0 = getelementptr i8, i8* %tmp8, i32 0
+        %p1 = getelementptr i8, i8* %tmp8, i32 1
+        %p2 = getelementptr i8, i8* %tmp8, i32 2
+        %p3 = getelementptr i8, i8* %tmp8, i32 3
         store i8 %d, i8* %p0
         store i8 %c, i8* %p1
         store i8 %b, i8* %p2
         store i8 %a, i8* %p3
-        %concat = load i32* %tmp
+        %concat = load i32, i32* %tmp
         ret i32 %concat
 }
 
@@ -44,14 +47,14 @@ define i64 @util_make_concat8(i8 %a, i8 %b, i8 %c, i8 %d,
                               i8 %e, i8 %f, i8 %g, i8 %h) {
         %tmp = alloca i64
         %tmp8 = bitcast i64* %tmp to i8*
-        %p0 = getelementptr i8* %tmp8, i32 0
-        %p1 = getelementptr i8* %tmp8, i32 1
-        %p2 = getelementptr i8* %tmp8, i32 2
-        %p3 = getelementptr i8* %tmp8, i32 3
-        %p4 = getelementptr i8* %tmp8, i32 4
-        %p5 = getelementptr i8* %tmp8, i32 5
-        %p6 = getelementptr i8* %tmp8, i32 6
-        %p7 = getelementptr i8* %tmp8, i32 7
+        %p0 = getelementptr i8, i8* %tmp8, i32 0
+        %p1 = getelementptr i8, i8* %tmp8, i32 1
+        %p2 = getelementptr i8, i8* %tmp8, i32 2
+        %p3 = getelementptr i8, i8* %tmp8, i32 3
+        %p4 = getelementptr i8, i8* %tmp8, i32 4
+        %p5 = getelementptr i8, i8* %tmp8, i32 5
+        %p6 = getelementptr i8, i8* %tmp8, i32 6
+        %p7 = getelementptr i8, i8* %tmp8, i32 7
         store i8 %h, i8* %p0
         store i8 %g, i8* %p1
         store i8 %f, i8* %p2
@@ -60,7 +63,7 @@ define i64 @util_make_concat8(i8 %a, i8 %b, i8 %c, i8 %d,
         store i8 %c, i8* %p5
         store i8 %b, i8* %p6
         store i8 %a, i8* %p7
-        %concat = load i64* %tmp
+        %concat = load i64, i64* %tmp
         ret i64 %concat
 }
 
@@ -68,4 +71,4 @@ define i32 @util_make_select(i32 %cond, i32 %t, i32 %f) {
         %cond_i1 = icmp ne i32 %cond, 0
         %res = select i1 %cond_i1, i32 %t, i32 %f
         ret i32 %res
-}
\ No newline at end of file
+}
diff --git a/test/Feature/_utils.leq36._ll b/test/Feature/_utils.leq36._ll
new file mode 100644
index 00000000..32a73bb1
--- /dev/null
+++ b/test/Feature/_utils.leq36._ll
@@ -0,0 +1,71 @@
+define i32 @util_make_and_i1(i32 %a, i32 %b) {
+        %a_i1 = icmp ne i32 %a, 0
+        %b_i1 = icmp ne i32 %b, 0
+        %res_i1 = and i1 %a_i1, %b_i1
+        %res = zext i1 %res_i1 to i32
+        ret i32 %res
+}
+
+define i32 @util_make_or_i1(i32 %a, i32 %b) {
+        %a_i1 = icmp ne i32 %a, 0
+        %b_i1 = icmp ne i32 %b, 0
+        %res_i1 = or i1 %a_i1, %b_i1
+        %res = zext i1 %res_i1 to i32
+        ret i32 %res
+}
+
+define i16 @util_make_concat2(i8 %a, i8 %b) {
+        %tmp = alloca i16
+        %tmp8 = bitcast i16* %tmp to i8*
+        %p0 = getelementptr i8* %tmp8, i32 0
+        %p1 = getelementptr i8* %tmp8, i32 1
+        store i8 %b, i8* %p0
+        store i8 %a, i8* %p1
+        %concat = load i16* %tmp
+        ret i16 %concat
+}
+
+define i32 @util_make_concat4(i8 %a, i8 %b, i8 %c, i8 %d) {
+        %tmp = alloca i32
+        %tmp8 = bitcast i32* %tmp to i8*
+        %p0 = getelementptr i8* %tmp8, i32 0
+        %p1 = getelementptr i8* %tmp8, i32 1
+        %p2 = getelementptr i8* %tmp8, i32 2
+        %p3 = getelementptr i8* %tmp8, i32 3
+        store i8 %d, i8* %p0
+        store i8 %c, i8* %p1
+        store i8 %b, i8* %p2
+        store i8 %a, i8* %p3
+        %concat = load i32* %tmp
+        ret i32 %concat
+}
+
+define i64 @util_make_concat8(i8 %a, i8 %b, i8 %c, i8 %d, 
+                              i8 %e, i8 %f, i8 %g, i8 %h) {
+        %tmp = alloca i64
+        %tmp8 = bitcast i64* %tmp to i8*
+        %p0 = getelementptr i8* %tmp8, i32 0
+        %p1 = getelementptr i8* %tmp8, i32 1
+        %p2 = getelementptr i8* %tmp8, i32 2
+        %p3 = getelementptr i8* %tmp8, i32 3
+        %p4 = getelementptr i8* %tmp8, i32 4
+        %p5 = getelementptr i8* %tmp8, i32 5
+        %p6 = getelementptr i8* %tmp8, i32 6
+        %p7 = getelementptr i8* %tmp8, i32 7
+        store i8 %h, i8* %p0
+        store i8 %g, i8* %p1
+        store i8 %f, i8* %p2
+        store i8 %e, i8* %p3
+        store i8 %d, i8* %p4
+        store i8 %c, i8* %p5
+        store i8 %b, i8* %p6
+        store i8 %a, i8* %p7
+        %concat = load i64* %tmp
+        ret i64 %concat
+}
+
+define i32 @util_make_select(i32 %cond, i32 %t, i32 %f) {
+        %cond_i1 = icmp ne i32 %cond, 0
+        %res = select i1 %cond_i1, i32 %t, i32 %f
+        ret i32 %res
+}
\ No newline at end of file
diff --git a/test/Intrinsics/objectsize.leq36.ll b/test/Intrinsics/objectsize.leq36.ll
new file mode 100644
index 00000000..7ad4b6fc
--- /dev/null
+++ b/test/Intrinsics/objectsize.leq36.ll
@@ -0,0 +1,33 @@
+; REQUIRES: lt-llvm-3.7
+; RUN: %llvmas %s -o=%t.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee -exit-on-error --output-dir=%t.klee-out -disable-opt %t.bc
+; ModuleID = 'objectsize.c'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind uwtable {
+entry:
+  %a = alloca i8*, align 8
+  %0 = load i8** %a, align 8
+  %1 = call i64 @llvm.objectsize.i64.p0i8(i8* %0, i1 true)
+  %cmp = icmp ne i64 %1, 0
+  br i1 %cmp, label %abort.block, label %continue.block
+
+continue.block:
+  %2 = load i8** %a, align 8
+  %3 = call i64 @llvm.objectsize.i64.p0i8(i8* %2, i1 false)
+  %cmp1 = icmp ne i64 %3, -1
+  br i1 %cmp1, label %abort.block, label %exit.block
+
+exit.block:
+  ret i32 0
+
+abort.block:
+  call void @abort()
+  unreachable
+}
+
+declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) nounwind readnone
+
+declare void @abort() noreturn nounwind
diff --git a/test/Intrinsics/objectsize.ll b/test/Intrinsics/objectsize.ll
index 4bb59596..3a111f99 100644
--- a/test/Intrinsics/objectsize.ll
+++ b/test/Intrinsics/objectsize.ll
@@ -1,3 +1,8 @@
+; Unfortunately LLVM 2.9 has a different suffix for the ``llvm.objectsize`` instrinsic
+; so this LLVM IR fails to verify for that version.
+;
+; LLVM 3.7 requires a type as the first argument to 'load'
+; REQUIRES: geq-llvm-3.7
 ; RUN: %llvmas %s -o=%t.bc
 ; RUN: rm -rf %t.klee-out
 ; RUN: %klee -exit-on-error --output-dir=%t.klee-out -disable-opt %t.bc
@@ -8,13 +13,13 @@ target triple = "x86_64-unknown-linux-gnu"
 define i32 @main() nounwind uwtable {
 entry:
   %a = alloca i8*, align 8
-  %0 = load i8** %a, align 8
+  %0 = load i8*, i8** %a, align 8
   %1 = call i64 @llvm.objectsize.i64.p0i8(i8* %0, i1 true)
   %cmp = icmp ne i64 %1, 0
   br i1 %cmp, label %abort.block, label %continue.block
 
 continue.block:
-  %2 = load i8** %a, align 8
+  %2 = load i8*, i8** %a, align 8
   %3 = call i64 @llvm.objectsize.i64.p0i8(i8* %2, i1 false)
   %cmp1 = icmp ne i64 %3, -1
   br i1 %cmp1, label %abort.block, label %exit.block
diff --git a/test/lit.cfg b/test/lit.cfg
index 00b429b6..e570f9b2 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -161,7 +161,7 @@ if int(config.llvm_version_major) == 2:
 
 # Add feature for the LLVM version in use, so it can be tested in REQUIRES and
 # XFAIL checks. We also add "not-XXX" variants, for the same reason.
-known_llvm_versions = set(["3.4", "3.5", "3.6"])
+known_llvm_versions = set(["3.4", "3.5", "3.6", "3.7", "3.8", "3.9"])
 current_llvm_version = "%s.%s" % (config.llvm_version_major,
                                   config.llvm_version_minor)
 config.available_features.add("llvm-" + current_llvm_version)
diff --git a/test/regression/2007-08-16-invalid-constant-value.c b/test/regression/2007-08-16-invalid-constant-value.c
index 5b17e68b..fd011f2e 100644
--- a/test/regression/2007-08-16-invalid-constant-value.c
+++ b/test/regression/2007-08-16-invalid-constant-value.c
@@ -1,3 +1,4 @@
+// REQUIRES: geq-llvm-3.7
 // RUN: rm -f %t4.out %t4.err %t4.log
 // RUN: %llvmgcc %s -emit-llvm -O2 -c -o %t1.bc
 // RUN: llvm-as -f %p/../Feature/_utils._ll -o %t2.bc
@@ -18,12 +19,12 @@ int main() {
   // value was being created when implied value did not
   // subtract using the proper type (so overflowed into
   // invalid bits)
-  if (util_make_concat2(a+0xCD,0xCD) == 0xABCD) { 
+  if (util_make_concat2(a + 0xCD, 0xCD) == 0xABCD) {
     assert(!klee_is_symbolic(a));
     printf("add constant case: %d\n", a);
   }
 
-  if (util_make_concat2(0x0B-a,0xCD) == 0xABCD) { 
+  if (util_make_concat2(0x0B - a, 0xCD) == 0xABCD) {
     assert(!klee_is_symbolic(a));
     printf("sub constant case: %d\n", a);
   }
diff --git a/test/regression/2007-08-16-invalid-constant-value.leq36.c b/test/regression/2007-08-16-invalid-constant-value.leq36.c
new file mode 100644
index 00000000..bf9f7561
--- /dev/null
+++ b/test/regression/2007-08-16-invalid-constant-value.leq36.c
@@ -0,0 +1,33 @@
+// REQUIRES: lt-llvm-3.7
+// RUN: rm -f %t4.out %t4.err %t4.log
+// RUN: %llvmgcc %s -emit-llvm -O2 -c -o %t1.bc
+// RUN: llvm-as -f %p/../Feature/_utils.leq36._ll -o %t2.bc
+// RUN: llvm-link %t1.bc %t2.bc -o %t3.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out %t3.bc
+
+#include <assert.h>
+
+#include "../Feature/utils.h"
+
+int main() {
+  unsigned char a;
+
+  klee_make_symbolic(&a, sizeof a, "a");
+
+  // demand was firing here because an invalid constant
+  // value was being created when implied value did not
+  // subtract using the proper type (so overflowed into
+  // invalid bits)
+  if (util_make_concat2(a+0xCD,0xCD) == 0xABCD) { 
+    assert(!klee_is_symbolic(a));
+    printf("add constant case: %d\n", a);
+  }
+
+  if (util_make_concat2(0x0B-a,0xCD) == 0xABCD) { 
+    assert(!klee_is_symbolic(a));
+    printf("sub constant case: %d\n", a);
+  }
+
+  return 0;
+}