mirror of
https://github.com/LLVMParty/llvm-nanobind
synced 2026-06-21 13:43:38 +00:00
254 lines
8.5 KiB
C++
254 lines
8.5 KiB
C++
/**
|
|
* Test: test_builder_cmp
|
|
* Tests LLVM Builder comparison operations
|
|
*
|
|
* LLVM-C APIs covered:
|
|
* - LLVMBuildICmp() with all LLVMIntPredicate values
|
|
* - LLVMBuildFCmp() with LLVMRealPredicate values
|
|
* - LLVMBuildSelect()
|
|
* - LLVMGetICmpPredicate(), LLVMGetFCmpPredicate()
|
|
*/
|
|
|
|
#include <cstdio>
|
|
#include <llvm-c/Analysis.h>
|
|
#include <llvm-c/Core.h>
|
|
|
|
const char *int_pred_name(LLVMIntPredicate pred) {
|
|
switch (pred) {
|
|
case LLVMIntEQ:
|
|
return "eq";
|
|
case LLVMIntNE:
|
|
return "ne";
|
|
case LLVMIntUGT:
|
|
return "ugt";
|
|
case LLVMIntUGE:
|
|
return "uge";
|
|
case LLVMIntULT:
|
|
return "ult";
|
|
case LLVMIntULE:
|
|
return "ule";
|
|
case LLVMIntSGT:
|
|
return "sgt";
|
|
case LLVMIntSGE:
|
|
return "sge";
|
|
case LLVMIntSLT:
|
|
return "slt";
|
|
case LLVMIntSLE:
|
|
return "sle";
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
const char *real_pred_name(LLVMRealPredicate pred) {
|
|
switch (pred) {
|
|
case LLVMRealPredicateFalse:
|
|
return "false";
|
|
case LLVMRealOEQ:
|
|
return "oeq";
|
|
case LLVMRealOGT:
|
|
return "ogt";
|
|
case LLVMRealOGE:
|
|
return "oge";
|
|
case LLVMRealOLT:
|
|
return "olt";
|
|
case LLVMRealOLE:
|
|
return "ole";
|
|
case LLVMRealONE:
|
|
return "one";
|
|
case LLVMRealORD:
|
|
return "ord";
|
|
case LLVMRealUNO:
|
|
return "uno";
|
|
case LLVMRealUEQ:
|
|
return "ueq";
|
|
case LLVMRealUGT:
|
|
return "ugt";
|
|
case LLVMRealUGE:
|
|
return "uge";
|
|
case LLVMRealULT:
|
|
return "ult";
|
|
case LLVMRealULE:
|
|
return "ule";
|
|
case LLVMRealUNE:
|
|
return "une";
|
|
case LLVMRealPredicateTrue:
|
|
return "true";
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
LLVMContextRef ctx = LLVMContextCreate();
|
|
LLVMModuleRef mod =
|
|
LLVMModuleCreateWithNameInContext("test_builder_cmp", ctx);
|
|
|
|
LLVMTypeRef i1 = LLVMInt1TypeInContext(ctx);
|
|
LLVMTypeRef i32 = LLVMInt32TypeInContext(ctx);
|
|
LLVMTypeRef f64 = LLVMDoubleTypeInContext(ctx);
|
|
LLVMTypeRef void_ty = LLVMVoidTypeInContext(ctx);
|
|
|
|
LLVMBuilderRef builder = LLVMCreateBuilderInContext(ctx);
|
|
|
|
// ==========================================
|
|
// Function 1: Integer comparisons
|
|
// ==========================================
|
|
LLVMTypeRef icmp_params[] = {i32, i32};
|
|
LLVMTypeRef icmp_ty = LLVMFunctionType(void_ty, icmp_params, 2, 0);
|
|
LLVMValueRef icmp_func = LLVMAddFunction(mod, "int_comparisons", icmp_ty);
|
|
LLVMValueRef a = LLVMGetParam(icmp_func, 0);
|
|
LLVMValueRef b = LLVMGetParam(icmp_func, 1);
|
|
LLVMSetValueName2(a, "a", 1);
|
|
LLVMSetValueName2(b, "b", 1);
|
|
|
|
LLVMBasicBlockRef icmp_entry =
|
|
LLVMAppendBasicBlockInContext(ctx, icmp_func, "entry");
|
|
LLVMPositionBuilderAtEnd(builder, icmp_entry);
|
|
|
|
// All integer predicates
|
|
LLVMValueRef icmp_eq = LLVMBuildICmp(builder, LLVMIntEQ, a, b, "eq");
|
|
LLVMValueRef icmp_ne = LLVMBuildICmp(builder, LLVMIntNE, a, b, "ne");
|
|
LLVMValueRef icmp_ugt = LLVMBuildICmp(builder, LLVMIntUGT, a, b, "ugt");
|
|
LLVMValueRef icmp_uge = LLVMBuildICmp(builder, LLVMIntUGE, a, b, "uge");
|
|
LLVMValueRef icmp_ult = LLVMBuildICmp(builder, LLVMIntULT, a, b, "ult");
|
|
LLVMValueRef icmp_ule = LLVMBuildICmp(builder, LLVMIntULE, a, b, "ule");
|
|
LLVMValueRef icmp_sgt = LLVMBuildICmp(builder, LLVMIntSGT, a, b, "sgt");
|
|
LLVMValueRef icmp_sge = LLVMBuildICmp(builder, LLVMIntSGE, a, b, "sge");
|
|
LLVMValueRef icmp_slt = LLVMBuildICmp(builder, LLVMIntSLT, a, b, "slt");
|
|
LLVMValueRef icmp_sle = LLVMBuildICmp(builder, LLVMIntSLE, a, b, "sle");
|
|
|
|
LLVMBuildRetVoid(builder);
|
|
|
|
// ==========================================
|
|
// Function 2: Float comparisons
|
|
// ==========================================
|
|
LLVMTypeRef fcmp_params[] = {f64, f64};
|
|
LLVMTypeRef fcmp_ty = LLVMFunctionType(void_ty, fcmp_params, 2, 0);
|
|
LLVMValueRef fcmp_func = LLVMAddFunction(mod, "float_comparisons", fcmp_ty);
|
|
LLVMValueRef x = LLVMGetParam(fcmp_func, 0);
|
|
LLVMValueRef y = LLVMGetParam(fcmp_func, 1);
|
|
LLVMSetValueName2(x, "x", 1);
|
|
LLVMSetValueName2(y, "y", 1);
|
|
|
|
LLVMBasicBlockRef fcmp_entry =
|
|
LLVMAppendBasicBlockInContext(ctx, fcmp_func, "entry");
|
|
LLVMPositionBuilderAtEnd(builder, fcmp_entry);
|
|
|
|
// Ordered comparisons (false if either is NaN)
|
|
LLVMValueRef fcmp_oeq = LLVMBuildFCmp(builder, LLVMRealOEQ, x, y, "oeq");
|
|
LLVMValueRef fcmp_ogt = LLVMBuildFCmp(builder, LLVMRealOGT, x, y, "ogt");
|
|
LLVMValueRef fcmp_oge = LLVMBuildFCmp(builder, LLVMRealOGE, x, y, "oge");
|
|
LLVMValueRef fcmp_olt = LLVMBuildFCmp(builder, LLVMRealOLT, x, y, "olt");
|
|
LLVMValueRef fcmp_ole = LLVMBuildFCmp(builder, LLVMRealOLE, x, y, "ole");
|
|
LLVMValueRef fcmp_one = LLVMBuildFCmp(builder, LLVMRealONE, x, y, "one");
|
|
LLVMValueRef fcmp_ord = LLVMBuildFCmp(builder, LLVMRealORD, x, y, "ord");
|
|
|
|
// Unordered comparisons (true if either is NaN)
|
|
LLVMValueRef fcmp_uno = LLVMBuildFCmp(builder, LLVMRealUNO, x, y, "uno");
|
|
LLVMValueRef fcmp_ueq = LLVMBuildFCmp(builder, LLVMRealUEQ, x, y, "ueq");
|
|
LLVMValueRef fcmp_ugt = LLVMBuildFCmp(builder, LLVMRealUGT, x, y, "ugt");
|
|
LLVMValueRef fcmp_uge = LLVMBuildFCmp(builder, LLVMRealUGE, x, y, "uge");
|
|
LLVMValueRef fcmp_ult = LLVMBuildFCmp(builder, LLVMRealULT, x, y, "ult");
|
|
LLVMValueRef fcmp_ule = LLVMBuildFCmp(builder, LLVMRealULE, x, y, "ule");
|
|
LLVMValueRef fcmp_une = LLVMBuildFCmp(builder, LLVMRealUNE, x, y, "une");
|
|
|
|
// Always true/false
|
|
LLVMValueRef fcmp_true =
|
|
LLVMBuildFCmp(builder, LLVMRealPredicateTrue, x, y, "always_true");
|
|
LLVMValueRef fcmp_false =
|
|
LLVMBuildFCmp(builder, LLVMRealPredicateFalse, x, y, "always_false");
|
|
|
|
LLVMBuildRetVoid(builder);
|
|
|
|
// ==========================================
|
|
// Function 3: Select instruction
|
|
// ==========================================
|
|
LLVMTypeRef sel_params[] = {i1, i32, i32};
|
|
LLVMTypeRef sel_ty = LLVMFunctionType(i32, sel_params, 3, 0);
|
|
LLVMValueRef sel_func = LLVMAddFunction(mod, "select_example", sel_ty);
|
|
LLVMValueRef cond = LLVMGetParam(sel_func, 0);
|
|
LLVMValueRef true_val = LLVMGetParam(sel_func, 1);
|
|
LLVMValueRef false_val = LLVMGetParam(sel_func, 2);
|
|
LLVMSetValueName2(cond, "cond", 4);
|
|
LLVMSetValueName2(true_val, "true_val", 8);
|
|
LLVMSetValueName2(false_val, "false_val", 9);
|
|
|
|
LLVMBasicBlockRef sel_entry =
|
|
LLVMAppendBasicBlockInContext(ctx, sel_func, "entry");
|
|
LLVMPositionBuilderAtEnd(builder, sel_entry);
|
|
|
|
LLVMValueRef selected =
|
|
LLVMBuildSelect(builder, cond, true_val, false_val, "selected");
|
|
LLVMBuildRet(builder, selected);
|
|
|
|
// ==========================================
|
|
// Function 4: Select with comparison
|
|
// ==========================================
|
|
LLVMTypeRef max_params[] = {i32, i32};
|
|
LLVMTypeRef max_ty = LLVMFunctionType(i32, max_params, 2, 0);
|
|
LLVMValueRef max_func = LLVMAddFunction(mod, "max", max_ty);
|
|
LLVMValueRef m_a = LLVMGetParam(max_func, 0);
|
|
LLVMValueRef m_b = LLVMGetParam(max_func, 1);
|
|
LLVMSetValueName2(m_a, "a", 1);
|
|
LLVMSetValueName2(m_b, "b", 1);
|
|
|
|
LLVMBasicBlockRef max_entry =
|
|
LLVMAppendBasicBlockInContext(ctx, max_func, "entry");
|
|
LLVMPositionBuilderAtEnd(builder, max_entry);
|
|
|
|
LLVMValueRef cmp_gt = LLVMBuildICmp(builder, LLVMIntSGT, m_a, m_b, "a_gt_b");
|
|
LLVMValueRef max_result = LLVMBuildSelect(builder, cmp_gt, m_a, m_b, "max");
|
|
LLVMBuildRet(builder, max_result);
|
|
|
|
LLVMDisposeBuilder(builder);
|
|
|
|
// Verify module
|
|
char *error = nullptr;
|
|
if (LLVMVerifyModule(mod, LLVMReturnStatusAction, &error)) {
|
|
fprintf(stderr, "; Verification failed: %s\n", error);
|
|
LLVMDisposeMessage(error);
|
|
LLVMDisposeModule(mod);
|
|
LLVMContextDispose(ctx);
|
|
return 1;
|
|
}
|
|
LLVMDisposeMessage(error);
|
|
|
|
// Print diagnostic comments
|
|
printf("; Test: test_builder_cmp\n");
|
|
printf(";\n");
|
|
printf("; Integer comparison predicates:\n");
|
|
printf("; eq, ne (equality)\n");
|
|
printf("; ugt, uge, ult, ule (unsigned)\n");
|
|
printf("; sgt, sge, slt, sle (signed)\n");
|
|
printf(";\n");
|
|
printf("; Float comparison predicates:\n");
|
|
printf("; Ordered: oeq, ogt, oge, olt, ole, one, ord\n");
|
|
printf("; Unordered: uno, ueq, ugt, uge, ult, ule, une\n");
|
|
printf("; Constant: true, false\n");
|
|
printf(";\n");
|
|
printf("; Predicate extraction:\n");
|
|
printf("; icmp_eq predicate: %s\n",
|
|
int_pred_name(LLVMGetICmpPredicate(icmp_eq)));
|
|
printf("; icmp_slt predicate: %s\n",
|
|
int_pred_name(LLVMGetICmpPredicate(icmp_slt)));
|
|
printf("; fcmp_oeq predicate: %s\n",
|
|
real_pred_name(LLVMGetFCmpPredicate(fcmp_oeq)));
|
|
printf("; fcmp_uno predicate: %s\n",
|
|
real_pred_name(LLVMGetFCmpPredicate(fcmp_uno)));
|
|
printf(";\n");
|
|
printf("; Select instruction: cond ? true_val : false_val\n");
|
|
printf("\n");
|
|
|
|
// Print module IR
|
|
char *ir = LLVMPrintModuleToString(mod);
|
|
printf("%s", ir);
|
|
LLVMDisposeMessage(ir);
|
|
|
|
// Cleanup
|
|
LLVMDisposeModule(mod);
|
|
LLVMContextDispose(ctx);
|
|
|
|
return 0;
|
|
}
|