Skip to content

Commit

Permalink
Merge pull request gcc-mirror#21 from GuillaumeGomez/pure-attr
Browse files Browse the repository at this point in the history
Add `pure` attribute support in libgccjit
  • Loading branch information
antoyo authored Jul 17, 2023
2 parents b4e6fe3 + 6dae9ee commit 03a7071
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 4 deletions.
3 changes: 3 additions & 0 deletions gcc/jit/jit-playback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,9 @@ new_function (location *loc,
/* See handle_returns_twice_attribute in gcc/c-family/c-attribs.cc. */
else if (attr == GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE)
DECL_IS_RETURNS_TWICE (fndecl) = 1;
/* See handle_pure_attribute in gcc/c-family/c-attribs.cc. */
else if (attr == GCC_JIT_FN_ATTRIBUTE_PURE)
DECL_PURE_P (fndecl) = 1;

const char* attribute = fn_attribute_to_string (attr);
if (attribute)
Expand Down
4 changes: 2 additions & 2 deletions gcc/jit/libgccjit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3874,7 +3874,7 @@ gcc_jit_target_info_release (gcc_jit_target_info *info)
delete info;
}

bool
int
gcc_jit_target_info_cpu_supports (gcc_jit_target_info *info,
const char *feature)
{
Expand All @@ -3887,7 +3887,7 @@ gcc_jit_target_info_arch (gcc_jit_target_info *info)
return info->m_arch;
}

bool
int
gcc_jit_target_info_supports_128bit_int (gcc_jit_target_info *info)
{
return info->m_supports_128bit_int;
Expand Down
5 changes: 3 additions & 2 deletions gcc/jit/libgccjit.h
Original file line number Diff line number Diff line change
Expand Up @@ -2080,14 +2080,14 @@ gcc_jit_context_get_target_info (gcc_jit_context *ctxt);
extern void
gcc_jit_target_info_release (gcc_jit_target_info *info);

extern bool
extern int
gcc_jit_target_info_cpu_supports (gcc_jit_target_info *info,
const char *feature);

extern const char *
gcc_jit_target_info_arch (gcc_jit_target_info *info);

extern bool
extern int
gcc_jit_target_info_supports_128bit_int (gcc_jit_target_info *info);

/* Given type "T", get type "T __attribute__ ((packed))". */
Expand All @@ -2105,6 +2105,7 @@ enum gcc_jit_fn_attribute
GCC_JIT_FN_ATTRIBUTE_VISIBILITY,
GCC_JIT_FN_ATTRIBUTE_COLD,
GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE,
GCC_JIT_FN_ATTRIBUTE_PURE,
};

/* Add an attribute to a function. */
Expand Down
33 changes: 33 additions & 0 deletions gcc/testsuite/jit.dg/jit.exp
Original file line number Diff line number Diff line change
Expand Up @@ -895,8 +895,41 @@ proc jit-verify-assembler-output { args } {
pass "${asm_filename} output pattern test, ${dg-output-text}"
verbose "Passed test for output pattern ${dg-output-text}" 3
}
}

# Assuming that a .s file has been written out named
# OUTPUT_FILENAME, check that the argument doesn't match
# the output file.
proc jit-verify-assembler-output-not { args } {
verbose "jit-verify-assembler: $args"

set dg-output-text [lindex $args 0]
verbose "dg-output-text: ${dg-output-text}"

upvar 2 name name
verbose "name: $name"

upvar 2 prog prog
verbose "prog: $prog"
set asm_filename [jit-get-output-filename $prog]
verbose " asm_filename: ${asm_filename}"

# Read the assembly file.
set f [open $asm_filename r]
set content [read $f]
close $f

# Verify that the assembly matches the regex.
if { [regexp ${dg-output-text} $content] } {
fail "${asm_filename} output pattern test, is ${content}, should match ${dg-output-text}"
verbose "Failed test for output pattern ${dg-output-text}" 3
} else {
pass "${asm_filename} output pattern test, ${dg-output-text}"
verbose "Passed test for output pattern ${dg-output-text}" 3
}
}


# Assuming that a .o file has been written out named
# OUTPUT_FILENAME, invoke the driver to try to turn it into
# an executable, and try to run the result.
Expand Down
134 changes: 134 additions & 0 deletions gcc/testsuite/jit.dg/test-pure-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 cold
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-pure-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__ ((pure))
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_PURE);

/* 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" } } */

0 comments on commit 03a7071

Please sign in to comment.