Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions gcc/jit/jit-playback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,10 @@ const char* fn_attribute_to_string(gcc_jit_fn_attribute attr)
return "cold";
case GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE:
return "returns_twice";
case GCC_JIT_FN_ATTRIBUTE_PURE:
return "pure";
case GCC_JIT_FN_ATTRIBUTE_CONST:
return "const";
}
return NULL;
}
Expand Down Expand Up @@ -675,6 +679,9 @@ new_function (location *loc,
/* See handle_pure_attribute in gcc/c-family/c-attribs.cc. */
else if (attr == GCC_JIT_FN_ATTRIBUTE_PURE)
DECL_PURE_P (fndecl) = 1;
/* See handle_const_attribute in gcc/c-family/c-attribs.cc. */
else if (attr == GCC_JIT_FN_ATTRIBUTE_CONST)
TREE_READONLY (fndecl) = 1;

const char* attribute = fn_attribute_to_string (attr);
if (attribute)
Expand Down
1 change: 1 addition & 0 deletions gcc/jit/libgccjit.h
Original file line number Diff line number Diff line change
Expand Up @@ -2106,6 +2106,7 @@ enum gcc_jit_fn_attribute
GCC_JIT_FN_ATTRIBUTE_COLD,
GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE,
GCC_JIT_FN_ATTRIBUTE_PURE,
GCC_JIT_FN_ATTRIBUTE_CONST,
};

/* Add an attribute to a function. */
Expand Down
134 changes: 134 additions & 0 deletions gcc/testsuite/jit.dg/test-const-attribute.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/* { dg-do compile { target x86_64-*-* } } */

#include <stdlib.h>
#include <stdio.h>

#include "libgccjit.h"

/* We don't want set_options() in harness.h to set -O3 to see that the const
attribute affects the optimizations. */
#define TEST_ESCHEWS_SET_OPTIONS
static void set_options (gcc_jit_context *ctxt, const char *argv0)
{
// Set "-O3".
gcc_jit_context_set_int_option(ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3);
}

#define TEST_COMPILING_TO_FILE
#define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_ASSEMBLER
#define OUTPUT_FILENAME "output-of-test-const-attribute.c.s"
#include "harness.h"

void
create_code (gcc_jit_context *ctxt, void *user_data)
{
/* Let's try to inject the equivalent of:
__attribute__ ((const))
int foo (int x);
int xxx(void)
{
int x = 45;
int sum = 0;

while (x >>= 1)
sum += foo (x) * 2;
return sum;
}
*/
gcc_jit_type *int_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);

/* Creating the `foo` function. */
gcc_jit_param *n =
gcc_jit_context_new_param (ctxt, NULL, int_type, "x");
gcc_jit_param *params[1] = {n};
gcc_jit_function *foo_func =
gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_IMPORTED,
int_type,
"foo",
1, params,
0);
gcc_jit_function_add_attribute(foo_func, GCC_JIT_FN_ATTRIBUTE_CONST);

/* Creating the `xxx` function. */
gcc_jit_function *xxx_func =
gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
int_type,
"xxx",
0, NULL,
0);

gcc_jit_block *block = gcc_jit_function_new_block (xxx_func, NULL);

/* Build locals: */
gcc_jit_lvalue *x =
gcc_jit_function_new_local (xxx_func, NULL, int_type, "x");
gcc_jit_lvalue *sum =
gcc_jit_function_new_local (xxx_func, NULL, int_type, "sum");

/* int x = 45 */
gcc_jit_block_add_assignment (
block, NULL,
x,
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 45));
/* int sum = 0 */
gcc_jit_block_add_assignment (
block, NULL,
sum,
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 0));

/* while (x >>= 1) { sum += foo (x) * 2; } */
gcc_jit_block *loop_cond =
gcc_jit_function_new_block (xxx_func, "loop_cond");
gcc_jit_block *loop_body =
gcc_jit_function_new_block (xxx_func, "loop_body");
gcc_jit_block *after_loop =
gcc_jit_function_new_block (xxx_func, "after_loop");

gcc_jit_block_end_with_jump (block, NULL, loop_cond);


/* if (x >>= 1) */
/* Since gccjit doesn't (yet?) have support for `>>=` operator, we will decompose it into:
`if (x = x >> 1)` */
gcc_jit_block_add_assignment_op (
loop_cond, NULL,
x,
GCC_JIT_BINARY_OP_RSHIFT,
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1));
/* The condition itself */
gcc_jit_block_end_with_conditional (
loop_cond, NULL,
gcc_jit_context_new_comparison (
ctxt, NULL,
GCC_JIT_COMPARISON_NE,
gcc_jit_lvalue_as_rvalue (x),
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 0)),
after_loop,
loop_body);

/* sum += foo (x) * 2; */
gcc_jit_rvalue *arg = gcc_jit_lvalue_as_rvalue(x);
gcc_jit_block_add_assignment_op (
loop_body, NULL,
x,
GCC_JIT_BINARY_OP_PLUS,
gcc_jit_context_new_binary_op (
ctxt, NULL,
GCC_JIT_BINARY_OP_MULT, int_type,
gcc_jit_context_new_call (ctxt, NULL, foo_func, 1, &arg),
gcc_jit_context_new_rvalue_from_int (
ctxt,
int_type,
2)));
gcc_jit_block_end_with_jump (loop_body, NULL, loop_cond);

/* return sum; */
gcc_jit_block_end_with_return (after_loop, NULL, gcc_jit_lvalue_as_rvalue(sum));
}

/* { dg-final { jit-verify-output-file-was-created "" } } */
/* Check that the loop was optimized away */
/* { dg-final { jit-verify-assembler-output-not "jne" } } */
2 changes: 1 addition & 1 deletion gcc/testsuite/jit.dg/test-pure-attribute.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#include "libgccjit.h"

/* We don't want set_options() in harness.h to set -O3 to see that the cold
/* We don't want set_options() in harness.h to set -O3 to see that the pure
attribute affects the optimizations. */
#define TEST_ESCHEWS_SET_OPTIONS
static void set_options (gcc_jit_context *ctxt, const char *argv0)
Expand Down