Skip to content

Instantly share code, notes, and snippets.

@nickdesaulniers
Last active April 10, 2024 20:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nickdesaulniers/8f20bea3bcdd9fe97219428ab6e8bf8b to your computer and use it in GitHub Desktop.
Save nickdesaulniers/8f20bea3bcdd9fe97219428ab6e8bf8b to your computer and use it in GitHub Desktop.
A test file I was using while trying to fix https://github.com/llvm/llvm-project/issues/20571. It tries to forcibly cause register exhaustion by using inline asm which clobbers all GPRs. In these cases, "rm" contrained operands should fall back to "m" rather than fail to compile.
// -Wno-asm-operand-widths
// void input_pressure(int x) {
// // asm ("# %0"::"m"(x):"r0","r1","r2","r3","r12","lr","r4","r5","r6","r7","r8","r9","r10","r11");
// asm (""::"m"(x));
// }
struct foo {
long a, b, c, d, e;
};
int zzz (struct foo my_foo) {
// void zzz (struct foo my_foo) {
// for i in $(seq 0 31); do echo -n "\"r$i\","; done
#ifdef __hexagon__
asm ("# %0"::"rm"(my_foo.b):"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r12","r13","r14","r15","r28","r10","r11","r16","r17","r18","r19","r20","r21","r22","r23","r24","r25","r26","r27");
#endif
#ifdef __x86_64__
// int x = 42;
// asm ("# %0"::"m"(x));
asm ("# %0 %1"::"rm"(my_foo.b),"rm"(my_foo.d):"ax","cx","dx","si","di","r8","r9","r10","r11","bx","bp","r14","r15","r12","r13");
asm ("# %0 %1":"=rm"(my_foo.b),"=rm"(my_foo.d)::"ax","cx","dx","si","di","r8","r9","r10","r11","bx","bp","r14","r15","r12","r13");
asm ("# %0 %1":"+rm"(my_foo.b),"+rm"(my_foo.d)::"ax","cx","dx","si","di","r8","r9","r10","r11","bx","bp","r14","r15","r12","r13");
// return my_foo.d;
asm ("# %0"::"rm"(my_foo.b));
asm ("# %0 %1"::"rm"(my_foo.b), "r"(my_foo.d));
asm ("# %0":"=rm"(my_foo.b));
asm ("# %0":"+rm"(my_foo.b));
// asm volatile ("# %0":"=r"(my_foo.b):"0"(my_foo.b));
#endif
#ifdef __i386__
asm ("# %0"::"rm"(my_foo.b):"ax","cx","dx","si","di","bx","bp");
asm ("# %0":"=rm"(my_foo.b)::"ax","cx","dx","si","di","bx","bp");
asm ("# %0":"+rm"(my_foo.b)::"ax","cx","dx","si","di","bx","bp");
#endif
#ifdef __lanai__
asm (""::"rm"(my_foo.b):"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","r13","r14","r15","r16","r17","r18","r19","r20","r21","r22","r23","r24","r25","r26","r27","r28","r29","r30","r31");
#endif
#ifdef __NVPTX__
// asm ("# %0 "::"rm"(my_foo.b):"r1");
#endif
// TODO: something fishy is going on for ARM.
#ifdef __arm__
// int x = 42;
// asm ("# %0"::"m"(x));
// asm ("# %0"::"rm"(my_foo.b):"r0","r1","r2","r3","r12","lr","r4","r5","r6","r7","r8","r9","r10","r11");
asm ("# %0 %1"::"rm"(my_foo.b),"rm"(my_foo.d):"r0","r1","r2","r3","r12","lr","r4","r5","r6","r7","r8","r9","r10","r11");
#endif
#ifdef __aarch64__
// int x = 42;
// asm ("# %0"::"m"(x));
asm ("# %0 %1"::"rm"(my_foo.b),"rm"(my_foo.d):"x8","x9","x10","x11","x12","x13","x14","x15","x16","x17","x18","x0","x1","x2","x3","x4","x5","x6","x7","x19","x20","x21","x22","x23","x24","x25","x26","x27","x28","x29","x30");
asm ("# %0 %1":"=rm"(my_foo.b),"=rm"(my_foo.d)::"x8","x9","x10","x11","x12","x13","x14","x15","x16","x17","x18","x0","x1","x2","x3","x4","x5","x6","x7","x19","x20","x21","x22","x23","x24","x25","x26","x27","x28","x29","x30");
asm ("# %0 %1":"+rm"(my_foo.b),"+rm"(my_foo.d)::"x8","x9","x10","x11","x12","x13","x14","x15","x16","x17","x18","x0","x1","x2","x3","x4","x5","x6","x7","x19","x20","x21","x22","x23","x24","x25","x26","x27","x28","x29","x30");
asm ("# %0"::"rm"(my_foo.b));
asm ("# %0 %1"::"rm"(my_foo.b), "r"(my_foo.d));
asm ("# %0":"=rm"(my_foo.b));
asm ("# %0":"+rm"(my_foo.b));
// asm ("# %0"::"rm"(my_foo.b):"x8","x9","x10","x11","x12","x13","x14","x15","x16","x17","x18","x0","x1","x2","x3","x4","x5","x6","x7","x19","x20","x21","x22","x23","x24","x25","x26","x27","x28","x29","x30");
// asm ("# %0"::"mr"(my_foo.b):"x8","x9","x10","x11","x12","x13","x14","x15","x16","x17","x18","x0","x1","x2","x3","x4","x5","x6","x7","x19","x20","x21","x22","x23","x24","x25","x26","x27","x28","x29","x30");
#endif
#ifdef __powerpc64__
// TODO: only long works, not int
asm ("# %0 %1"::"rm"(my_foo.b),"rm"(my_foo.d):"r4","r5","r6","r7","r8","r9","r10","r11","r12","r0","r30","r29","r28","r27","r26","r25","r24","r23","r22","r21","r20","r19","r18","r17","r16","r15","r14","r31","r3");
// long x = 42;
// asm ("# %0"::"m"(x));
#endif
#ifdef __riscv
// int x = 42;
// asm ("# %0"::"m"(x));
asm ("# %0 %1"::"rm"(my_foo.b), "rm"(my_foo.d):"a1","a2","a3","a4","a5","a6","a7","t0","t1","t2","t3","t4","t5","t6","s0","s1","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","ra");
#endif
return my_foo.a;
}
; Generate test cases with:
; $ llc -mtriple=i686 test_cases.ll -stop-after={greedy|virtregrewriter} -o -
;define void @input_no_pressure (i32 inreg %x) nounwind {
; call void asm "# $0", "rm"(i32 %x)
; ret void
;}
;
;define i32 @output_no_pressure () nounwind {
; %1 = call i32 asm "# $0", "=rm"()
; ret i32 %1
;}
;
;define void @input_pressure (i32 inreg %x) nounwind {
; ; call void asm "", "rm,~{bx},~{cx},~{dx},~{si},~{di},~{bp},~{memory}"(i32 %x)
; call void asm "# $0", "rm,~{ax},~{bx},~{cx},~{dx},~{si},~{di},~{bp}"(i32 %x)
; ret void
;}
; define i32 @output_pressure0 () nounwind {
; %1 = call i32 asm "# $0", "=rm,~{ax},~{bx},~{cx},~{dx},~{si},~{di},~{bp}"()
; ret i32 %1
; }
;; TODO: clang generates code more like:
;; CodeGenFunction::EmitAsmStmt clang/lib/CodeGen/CGStmt.cpp +2423
;define i32 @output_pressure () nounwind {
; %x = alloca i32, align 4
; call void asm "# $0", "=*rm,~{ax},~{bx},~{cx},~{dx},~{si},~{di},~{bp}"(ptr nonnull elementtype(i32) %x)
; %1 = load i32, ptr %x, align 4
; ret i32 %1
;}
; define i32 @inout_no_pressure (i32 inreg %x) nounwind {
; %1 = call i32 asm "# $0", "=rm,0"(i32 %x)
; ret i32 %1
; }
; define i32 @inout_pressure (i32 inreg %x) nounwind {
; %1 = call i32 asm "# $0 $1", "=rm,0,~{ax},~{bx},~{cx},~{dx},~{si},~{di},~{bp}"(i32 %x)
; ret i32 %1
; }
; asm goto
;define void @input_no_pressure_goto (i32 inreg %x) nounwind {
; callbr void asm "# $0 $1", "rm,!i"(i32 %x)
; to label %ft [label %ij]
;ft:
; br label %ij
;ij:
; ret void
;}
;
;define i32 @output_no_pressure_goto () nounwind {
; %1 = callbr i32 asm "# $0 $1", "=rm,!i"()
; to label %ft [label %ij]
;ft:
; %2 = add nsw i32 %1, 1
; ret i32 %2
;ij:
; ret i32 %1
;}
;
define void @input_pressure_goto (i32 inreg %x) nounwind {
; call void asm "", "rm,~{bx},~{cx},~{dx},~{si},~{di},~{bp},~{memory}"(i32 %x)
callbr void asm "# $0 $1", "rm,!i,~{ax},~{bx},~{cx},~{dx},~{si},~{di},~{bp}"(i32 %x)
to label %ft [label %ij]
ft:
br label %ij
ij:
ret void
}
;define i32 @output_pressure0_goto () nounwind {
; %1 = callbr i32 asm "# $0 $1", "=rm,!i,~{ax},~{bx},~{cx},~{dx},~{si},~{di},~{bp}"()
; to label %ft [label %ij]
;ft:
; ret i32 %1
;ij:
; ret i32 %1
; }
;define i32 @output_pressure_goto () nounwind {
; %x = alloca i32, align 4
; callbr void asm "# $0 $1", "=*rm,!i,~{ax},~{bx},~{cx},~{dx},~{si},~{di},~{bp}"(ptr nonnull elementtype(i32) %x)
; to label %ft [label %ft]
;ft:
; %1 = load i32, ptr %x, align 4
; ret i32 %1
;}
; define i32 @inout_no_pressure_goto (i32 inreg %x) nounwind {
; %1 = callbr i32 asm "# $0 $1", "=rm,!i,0"(i32 %x)
; to label %ft [label %ft]
;ft:
; ret i32 %1
; }
; TODO: greedy is not spilling this correctly!
; define i32 @inout_pressure_goto (i32 inreg %x) nounwind {
; %1 = callbr i32 asm "# $0 $1 $2", "=rm,0,!i,~{ax},~{bx},~{cx},~{dx},~{si},~{di},~{bp}"(i32 %x)
; to label %ft [label %ft]
;ft:
; ret i32 %1
; }
define void @foo(i32 %x) nounwind {
call void asm "# $0", "rm,~{eax},~{bx},~{cx},~{dx},~{si},~{di},~{bp}"(i32 %x)
ret void
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment