[llvm] [AVR] Explicitly set flag 'hasSideEffects' of instructions (PR #173660)
Ben Shi via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 26 05:03:33 PST 2025
https://github.com/benshi001 created https://github.com/llvm/llvm-project/pull/173660
None
>From fc62ba70b1a0953a2c20a09fa90f4f6036bfd012 Mon Sep 17 00:00:00 2001
From: Ben Shi <bennshi at tencent.com>
Date: Fri, 26 Dec 2025 18:26:48 +0800
Subject: [PATCH] [AVR] Set implicit flag 'hasSideEffects' to instructions
---
llvm/lib/Target/AVR/AVRInstrFormats.td | 3 +-
llvm/lib/Target/AVR/AVRInstrInfo.td | 78 ++++++++++++++------------
2 files changed, 44 insertions(+), 37 deletions(-)
diff --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td
index 72ea3bc1f460d..c721d655fec7c 100644
--- a/llvm/lib/Target/AVR/AVRInstrFormats.td
+++ b/llvm/lib/Target/AVR/AVRInstrFormats.td
@@ -531,6 +531,7 @@ class FSK<bit f, dag outs, dag ins, string asmstr, list<dag> pattern>
class ExtensionPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
: Pseudo<outs, ins, asmstr, pattern> {
let Defs = [SREG];
+ let hasSideEffects = 0;
}
class StorePseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
@@ -548,6 +549,6 @@ class SelectPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
class ShiftPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
: Pseudo<outs, ins, asmstr, pattern> {
let usesCustomInserter = 1;
-
+ let hasSideEffects = 0;
let Defs = [SREG];
}
diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td
index b5f13c055a860..c219645855755 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.td
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.td
@@ -361,7 +361,8 @@ let Defs = [SP, SREG], Uses = [SP] in {
//===----------------------------------------------------------------------===//
// Addition
//===----------------------------------------------------------------------===//
-let isCommutable = 1, Constraints = "$src = $rd", Defs = [SREG] in {
+let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $rd",
+ Defs = [SREG] in {
// ADD Rd, Rr
// Adds two 8-bit registers.
def ADDRdRr : FRdRr<0b0000, 0b11, (outs GPR8:$rd),(ins GPR8:$src, GPR8:$rr),
@@ -408,7 +409,7 @@ let isCommutable = 1, Constraints = "$src = $rd", Defs = [SREG] in {
//===----------------------------------------------------------------------===//
// Subtraction
//===----------------------------------------------------------------------===//
-let Constraints = "$rs = $rd", Defs = [SREG] in {
+let hasSideEffects = 0, Constraints = "$rs = $rd", Defs = [SREG] in {
// SUB Rd, Rr
// Subtracts the 8-bit value of Rr from Rd and places the value in Rd.
def SUBRdRr : FRdRr<0b0001, 0b10, (outs GPR8:$rd), (ins GPR8:$rs, GPR8:$rr),
@@ -474,7 +475,7 @@ let Constraints = "$rs = $rd", Defs = [SREG] in {
//===----------------------------------------------------------------------===//
// Increment and Decrement
//===----------------------------------------------------------------------===//
-let Constraints = "$src = $rd", Defs = [SREG] in {
+let hasSideEffects = 0, Constraints = "$src = $rd", Defs = [SREG] in {
def INCRd : FRd<0b1001, 0b0100011, (outs GPR8:$rd), (ins GPR8:$src),
"inc\t$rd",
[(set i8:$rd, (add i8:$src, 1))]>;
@@ -488,7 +489,7 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
// Multiplication
//===----------------------------------------------------------------------===//
-let isCommutable = 1, Defs = [R1, R0, SREG] in {
+let hasSideEffects = 0, isCommutable = 1, Defs = [R1, R0, SREG] in {
// MUL Rd, Rr
// Multiplies Rd by Rr and places the result into R1:R0.
let usesCustomInserter = 1 in {
@@ -518,14 +519,15 @@ let isCommutable = 1, Defs = [R1, R0, SREG] in {
Requires<[SupportsMultiplication]>;
}
-let Defs =
+// Set hasSideEffects = 1 to prevent it is considered dead.
+let hasSideEffects = 1, Defs =
[R15, R14, R13, R12, R11, R10, R9, R8, R7, R6, R5, R4, R3, R2, R1, R0] in
def DESK : FDES<(outs), (ins i8imm:$k), "des\t$k", []>, Requires<[HasDES]>;
//===----------------------------------------------------------------------===//
// Logic
//===----------------------------------------------------------------------===//
-let Constraints = "$src = $rd", Defs = [SREG] in {
+let hasSideEffects = 0, Constraints = "$src = $rd", Defs = [SREG] in {
// Register-Register logic instructions (which have the
// property of commutativity).
let isCommutable = 1 in {
@@ -599,7 +601,7 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
//===----------------------------------------------------------------------===//
// One's/Two's Complement
//===----------------------------------------------------------------------===//
-let Constraints = "$src = $rd", Defs = [SREG] in {
+let hasSideEffects = 0, Constraints = "$src = $rd", Defs = [SREG] in {
def COMRd : FRd<0b1001, 0b0100000, (outs GPR8:$rd), (ins GPR8:$src),
"com\t$rd", [(set i8:$rd, (not i8:$src))]>;
@@ -620,7 +622,6 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
// neg Rd+1
// neg Rd
// sbc Rd+1, r1
- let hasSideEffects=0 in
def NEGWRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src, GPR8:$zero),
"negw\t$rd", []>;
}
@@ -701,7 +702,7 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
//===----------------------------------------------------------------------===//
// Compare operations.
//===----------------------------------------------------------------------===//
-let Defs = [SREG] in {
+let hasSideEffects = 0, Defs = [SREG] in {
// CPSE Rd, Rr
// Compare Rd and Rr, skipping the next instruction if they are equal.
let isBarrier = 1, isBranch = 1, isTerminator = 1 in
@@ -861,7 +862,7 @@ let hasSideEffects = 0 in {
}
// Load immediate values into registers.
-let isReMaterializable = 1 in {
+let hasSideEffects = 0, isReMaterializable = 1 in {
def LDIRdK : FRdK<0b1110, (outs LD8:$rd), (ins imm_ldi8:$k), "ldi\t$rd, $k",
[(set i8:$rd, imm:$k)]>;
@@ -875,7 +876,7 @@ let isReMaterializable = 1 in {
}
// Load from data space into register.
-let mayLoad = 1, isReMaterializable = 1 in {
+let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
def LDSRdK : F32DM<0b0, (outs GPR8:$rd), (ins imm16:$k), "lds\t$rd, $k",
[(set i8:$rd, (load imm:$k))]>,
Requires<[HasSRAM, HasNonTinyEncoding]>;
@@ -896,7 +897,7 @@ let mayLoad = 1, isReMaterializable = 1 in {
}
// Indirect loads.
-let mayLoad = 1, isReMaterializable = 1 in {
+let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
def LDRdPtr : FSTLD<0, 0b00, (outs GPR8:$reg), (ins PTRREGS:$ptrreg),
"ld\t$reg, $ptrreg",
[(set GPR8:$reg, (load i16:$ptrreg))]>,
@@ -948,7 +949,7 @@ let mayLoad = 1, hasSideEffects = 0,
}
// Load indirect with displacement operations.
-let mayLoad = 1, isReMaterializable = 1 in {
+let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
def LDDRdPtrQ : FSTDLDD<0, (outs GPR8:$reg), (ins memri:$memri),
"ldd\t$reg, $memri",
[(set i8:$reg, (load addr:$memri))]>,
@@ -986,23 +987,22 @@ let mayLoad = 1, isReMaterializable = 1 in {
// The pseudo expansion pass trivially expands this into LDDWRdPtrQ.
//
// This instruction may be removed once PR13375 is fixed.
- let hasSideEffects = 0 in
def LDDWRdYQ : Pseudo<(outs DREGS:$dst), (ins memri:$memri),
"lddw\t$dst, $memri", []>,
Requires<[HasSRAM]>;
}
-let mayLoad = 1, isReMaterializable = 1 in
+let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in
class AtomicLoad<PatFrag Op, RegisterClass DRC, RegisterClass PTRRC>
: Pseudo<(outs DRC:$rd), (ins PTRRC:$rr), "atomic_op",
[(set DRC:$rd, (Op i16:$rr))]>;
-let mayStore = 1 in
+let hasSideEffects = 0, mayStore = 1 in
class AtomicStore<PatFrag Op, RegisterClass DRC, RegisterClass PTRRC>
: Pseudo<(outs), (ins PTRRC:$rd, DRC:$rr), "atomic_op",
[(Op DRC:$rr, i16:$rd)]>;
-let mayLoad = 1, mayStore = 1 in
+let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in
class AtomicLoadOp<PatFrag Op, RegisterClass DRC, RegisterClass PTRRC>
: Pseudo<(outs DRC:$rd), (ins PTRRC:$rr, DRC:$operand), "atomic_op",
[(set DRC:$rd, (Op i16:$rr, DRC:$operand))]>;
@@ -1025,7 +1025,7 @@ def AtomicStore16 : AtomicStore<atomic_store_16, DREGS, PTRDISPREGS>;
class AtomicLoadOp8<PatFrag Op> : AtomicLoadOp<Op, GPR8, PTRREGS>;
class AtomicLoadOp16<PatFrag Op> : AtomicLoadOp<Op, DREGS, PTRDISPREGS>;
-let usesCustomInserter=1 in {
+let usesCustomInserter = 1, Defs = [SREG] in {
def AtomicLoadAdd8 : AtomicLoadOp8<atomic_load_add_i8>;
def AtomicLoadAdd16 : AtomicLoadOp16<atomic_load_add_i16>;
def AtomicLoadSub8 : AtomicLoadOp8<atomic_load_sub_i8>;
@@ -1038,11 +1038,12 @@ let usesCustomInserter=1 in {
def AtomicLoadXor16 : AtomicLoadOp16<atomic_load_xor_i16>;
}
+let hasSideEffects = 1 in
def AtomicFence
: Pseudo<(outs), (ins), "atomic_fence", [(atomic_fence timm, timm)]>;
// Indirect store from register to data space.
-let mayStore = 1 in {
+let hasSideEffects = 0, mayStore = 1 in {
def STSKRr : F32DM<0b1, (outs), (ins imm16:$k, GPR8:$rd), "sts\t$k, $rd",
[(store i8:$rd, imm:$k)]>,
Requires<[HasSRAM, HasNonTinyEncoding]>;
@@ -1058,7 +1059,7 @@ let mayStore = 1 in {
// Expands to:
// sts Rr+1, (K+1:K) + 1
// sts Rr, (K+1:K)
-let mayStore = 1 in
+let hasSideEffects = 0, mayStore = 1 in
def STSWKRr : Pseudo<(outs), (ins i16imm:$dst, DREGS:$src),
"stsw\t$dst, $src", [(store i16:$src, imm:$dst)]>,
Requires<[HasSRAM, HasNonTinyEncoding]>;
@@ -1066,7 +1067,7 @@ def STSWKRr : Pseudo<(outs), (ins i16imm:$dst, DREGS:$src),
// Indirect stores.
// ST P, Rr
// Stores the value of Rr into the location addressed by pointer P.
-let mayStore = 1 in
+let hasSideEffects = 0, mayStore = 1 in
def STPtrRr : FSTLD<1, 0b00, (outs), (ins PTRREGS:$ptrreg, GPR8:$reg),
"st\t$ptrreg, $reg", [(store GPR8:$reg, i16:$ptrreg)]>,
Requires<[HasSRAM]>;
@@ -1081,14 +1082,14 @@ def STPtrRr : FSTLD<1, 0b00, (outs), (ins PTRREGS:$ptrreg, GPR8:$reg),
// st P+, Rr
// st P+, Rr+1
// subiw P, q+2
-let mayStore = 1 in
+let hasSideEffects = 0, mayStore = 1 in
def STWPtrRr : Pseudo<(outs), (ins PTRDISPREGS:$ptrreg, DREGS:$reg),
"stw\t$ptrreg, $reg", [(store i16:$reg, i16:$ptrreg)]>,
Requires<[HasSRAM]>;
// Indirect stores (with postincrement or predecrement).
-let mayStore = 1, Constraints = "$ptrreg = $base_wb, at earlyclobber $base_wb" in {
-
+let hasSideEffects = 0, mayStore = 1,
+ Constraints = "$ptrreg = $base_wb, at earlyclobber $base_wb" in {
// ST P+, Rr
// Stores the value of Rr into the location addressed by pointer P.
// Post increments P.
@@ -1143,7 +1144,7 @@ let mayStore = 1, Constraints = "$ptrreg = $base_wb, at earlyclobber $base_wb" in {
// STD P+q, Rr
// Stores the value of Rr into the location addressed by pointer P with a
// displacement of q. Does not modify P.
-let mayStore = 1 in
+let hasSideEffects = 0, mayStore = 1 in
def STDPtrQRr : FSTDLDD<1, (outs), (ins memri:$memri, GPR8:$reg),
"std\t$memri, $reg", [(store i8:$reg, addr:$memri)]>,
Requires<[HasSRAM, HasNonTinyEncoding]>;
@@ -1160,7 +1161,7 @@ def STDPtrQRr : FSTDLDD<1, (outs), (ins memri:$memri, GPR8:$reg),
// st P+, Rr
// st P+, Rr+1
// subiw P, q+2
-let mayStore = 1 in
+let hasSideEffects = 0, mayStore = 1 in
def STDWPtrQRr : Pseudo<(outs), (ins memri:$memri, DREGS:$src),
"stdw\t$memri, $src", [(store i16:$src, addr:$memri)]>,
Requires<[HasSRAM]>;
@@ -1226,7 +1227,7 @@ let mayLoad = 1, hasSideEffects = 0 in {
}
// These pseudos are combination of the OUT and ELPM instructions.
- let Defs = [R31R30], hasSideEffects = 1 in {
+ let Defs = [R31R30], mayStore = 1 in {
def ELPMBRdZPi : Pseudo<(outs GPR8:$dst), (ins ZREG:$z, LD8:$p),
"elpmb\t$dst, $z+, $p", []>,
Requires<[HasELPMX]>;
@@ -1238,12 +1239,12 @@ let mayLoad = 1, hasSideEffects = 0 in {
}
// Store program memory operations.
-let Uses = [R1, R0], mayStore = 1 in {
+let Uses = [R1, R0], mayStore = 1, hasSideEffects = 0 in {
let Uses = [R31R30] in
def SPM : F16<0b1001010111101000, (outs), (ins), "spm", []>,
Requires<[HasSPM]>;
- let Defs = [R31R30] in
+ let Defs = [R31R30] in
def SPMZPi : F16<0b1001010111111000, (outs), (ins ZREG:$z), "spm $z+", []>,
Requires<[HasSPMX]> {
bits<0> z;
@@ -1251,7 +1252,7 @@ let Uses = [R1, R0], mayStore = 1 in {
}
// Read data from IO location operations.
-let mayLoad = 1 in {
+let hasSideEffects = 1, mayLoad = 1 in {
def INRdA : FIORdA<(outs GPR8:$rd), (ins imm_port6:$A), "in\t$rd, $A",
[(set i8:$rd, (load ioaddr8:$A))]>;
@@ -1260,7 +1261,7 @@ let mayLoad = 1 in {
}
// Write data to IO location operations.
-let mayStore = 1 in {
+let hasSideEffects = 1, mayStore = 1 in {
def OUTARr : FIOARr<(outs), (ins imm_port6:$A, GPR8:$rr), "out\t$A, $rr",
[(store i8:$rr, ioaddr8:$A)]>;
@@ -1291,7 +1292,7 @@ let Defs = [SP], Uses = [SP], hasSideEffects = 0 in {
}
// Read-Write-Modify (RMW) instructions.
-let mayLoad = 1, mayStore = 1 in {
+let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in {
def XCHZRd : FZRd<0b100, (outs GPR8:$rd), (ins ZREG:$z), "xch\t$z, $rd", []>,
Requires<[SupportsRMW]>;
@@ -1310,7 +1311,7 @@ let mayLoad = 1, mayStore = 1 in {
//===----------------------------------------------------------------------===//
// Bit shift/rotate operations.
-let Constraints = "$src = $rd", Defs = [SREG] in {
+let hasSideEffects = 0, Constraints = "$src = $rd", Defs = [SREG] in {
// 8-bit LSL is an alias of ADD Rd, Rd
def LSLWRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "lslw\t$rd",
@@ -1389,14 +1390,14 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
// SWAP Rd
// Swaps the high and low nibbles in a register.
-let Constraints = "$src = $rd" in
+let hasSideEffects = 0, Constraints = "$src = $rd" in
def SWAPRd : FRd<0b1001, 0b0100010, (outs GPR8:$rd), (ins GPR8:$src),
"swap\t$rd", [(set i8:$rd, (AVRSwap i8:$src))]>;
// IO register bit set/clear operations.
//: TODO: add patterns when popcount(imm)==2 to be expanded with 2 sbi/cbi
// instead of in+ori+out which requires one more instr.
-let mayStore = 1 in {
+let hasSideEffects = 1, mayStore = 1 in {
def SBIAb : FIOBIT<0b10, (outs), (ins imm_port5:$addr, i8imm:$b),
"sbi\t$addr, $b",
[(store(or(i8(load lowioaddr8:$addr)), iobitpos8:$b),
@@ -1483,6 +1484,7 @@ def : InstAlias<"cli", (BCLRs 7)>;
// Breakpoint instruction
// ---------
// <|1001|0101|1001|1000>
+let hasSideEffects = 1 in
def BREAK : F16<0b1001010110011000, (outs), (ins), "break", []>,
Requires<[HasBREAK]>;
@@ -1490,18 +1492,22 @@ def BREAK : F16<0b1001010110011000, (outs), (ins), "break", []>,
// No-operation instruction
// ---------
// <|0000|0000|0000|0000>
+// Set `hasSideEffects = 1` in case it is considered dead.
+let hasSideEffects = 1 in
def NOP : F16<0b0000000000000000, (outs), (ins), "nop", []>;
// SLEEP
// Sleep instruction
// ---------
// <|1001|0101|1000|1000>
+let hasSideEffects = 1 in
def SLEEP : F16<0b1001010110001000, (outs), (ins), "sleep", []>;
// WDR
// Watchdog reset
// ---------
// <|1001|0101|1010|1000>
+let hasSideEffects = 1 in
def WDR : F16<0b1001010110101000, (outs), (ins), "wdr", []>;
//===----------------------------------------------------------------------===//
@@ -1625,7 +1631,7 @@ def Asr32 : ShiftPseudo<(outs DREGS:$dstlo, DREGS:$dsthi),
(AVRasrw i16:$srclo, i16:$srchi, i8:$cnt))]>;
// lowered to a copy from the zero register.
-let usesCustomInserter=1 in
+let usesCustomInserter = 1, hasSideEffects = 0 in
def CopyZero : Pseudo<(outs GPR8:$rd), (ins), "clrz\t$rd", [(set i8:$rd, 0)]>;
//===----------------------------------------------------------------------===//
More information about the llvm-commits
mailing list