Skip to content

analogWrite - PWM Problem in IDE-Version 1.8.10 #339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Nnambles opened this issue Jan 22, 2020 · 34 comments
Closed

analogWrite - PWM Problem in IDE-Version 1.8.10 #339

Nnambles opened this issue Jan 22, 2020 · 34 comments
Assignees

Comments

@Nnambles
Copy link

There is a Bug in Version 1.8.10 of the Arduino IDE using analogWrite() for PWM on Arduino Mega 2560. If i use analogWrite() with any value for the pwm-Pins once in the loop()-Method everything works fine. If I put a second call of analogWrite() with the same pin and any value that is not 0 or 255, nothing happens. The loop-Method keeps on working, but the PWM-Pin used in analogWrite() shows an continous output of 0V. In Version 1.8.9 the same programm works fine.

@alaqadi
Copy link

alaqadi commented Feb 1, 2020

I discovered the same issue today as I teach Arduino to my students , and a few of them has the issue of when putting a second analogWrite() for a second PWM on the same pin or a different pin, it will case online one PWM signal to appear. This happened on Mega 2560. After testing multiple boards with multiple Oscilliscopes, I was finally to find the reason as I tested one board on a computer that had 1.8.8 and it worked fine. I tried 1.8.11 it had the same problem.
Please fix or remove 1.8.10 and 1.8.11 from the main download page. This is a major bug

@facchinm
Copy link
Member

Should be moved to ArduinoCore-AVR and fixed ASAP (although I think it's due to the compiler update more than any core update)

@Rocketct
Copy link

Rocketct commented Feb 25, 2020

Hi all, i made some tests, and i found that:

  1. Seems taht as @facchinm sayas the issue does not depend from the core AVR but from the compiler;
  2. setting, for the analogWrite, the attribute __attribute__((optimize(**...**))); and giving some properly value to the optimize it is possible make it works properly, i get the following results:
  • __attribute__((optimize("-O0")));
    WORKS:
    The sketch use:
    flash: 2332 byte
    ram: 9 byte

  • __attribute__((optimize("-01")));
    WORKS:
    Sketch size:
    flash 1964 byte
    ram: 9 byte

  • __attribute__((optimize("-02")));
    WORKS
    Sketch size:
    flash: 1830 byte
    ram: 9 byte

  • __attribute__((optimize("-0s")));
    NOT WORKS

Sketch size:
flash: 1830 byte
ram: 9 byte

  • Without any __attribute__
    NOT WORKS
    Sketch size:
    flash: 1836 byte
    ram: 9 byte

the AVR-Core patch to test it is the following:

diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h
index 91eeb16..b86496f 100644
--- a/cores/arduino/Arduino.h
+++ b/cores/arduino/Arduino.h
@@ -136,7 +136,7 @@ void digitalWrite(uint8_t pin, uint8_t val);
 int digitalRead(uint8_t pin);
 int analogRead(uint8_t pin);
 void analogReference(uint8_t mode);
-void analogWrite(uint8_t pin, int val);
+void analogWrite(uint8_t pin, int val) __attribute__((optimize("-O0"))); unsigned long millis(void);
 unsigned long micros(void);

@matthijskooijman
Copy link
Collaborator

Can anyone post a short example sketch that shows the problem, along with a description of what (incorrect) output it shows?

@Rocketct
Copy link

Rocketct commented Feb 25, 2020

yes sure:

void writeTest(int a) {
  analogWrite(3, a);
  delay(5000);
}

void setup() {
}

void loop()
{
  writeTest(128);
  writeTest(64);
}

if you check the output of the pin 3 with an oscilloscope, the correct output should be two PWM wave were in the first you have the 50% of the duty cycle and in the seconds the 25%, (two different square wave in other words), in the incorrect case the pin 3 doesn't show any activities

@matthijskooijman
Copy link
Collaborator

@Rocketct And can you also describe the output you get when you run this particular sketch?

@Rocketct
Copy link

Rocketct commented Feb 25, 2020

yes sorry added on the previous comment let me know if clear 😄

@matthijskooijman
Copy link
Collaborator

@Rocketct, Thanks, perfectly clear. I have tried your sketch and looked at the generated machine code, which actually looks to be correct. I don't have an Arduino at hand right now to check if the same problem occurs for me, though.

What Arduino did you test this with?

@PaulStoffregen
Copy link
Contributor

I can confirm the problem happens with Arduino Mega using Arduino IDE 1.8.12.

However, Arduino Uno seems to be unaffected. I got PWM output in pin 3 with the code as shipped.

@PaulStoffregen
Copy link
Contributor

PaulStoffregen commented Feb 25, 2020

On Arduino Mega, I see this on pin 3:

file

and upload again with this with this in Arduino.h:

void analogWrite(uint8_t pin, int val) __attribute__((optimize("-O0")));

I get this on pin 3:

file2

@PaulStoffregen
Copy link
Contributor

Here's how I tested (an old clone ... sorry, the only Mega board I have...)

DSC_0729_web

@matthijskooijman
Copy link
Collaborator

Ah, confirmed here: Uno works, Mega is broken. Gotta run now, I hope to look at the assembly again in the next days.

@matthijskooijman
Copy link
Collaborator

I had a look at the generated assembly. Most is similar, except that the analogWrite has a jump table rather than nested branches to select between the different timers (probably because the mega has more timer pins). I originally thought the jump table handling was messed up (wrong RAMPZ value), but while annotating the assembly below, I realized it did seem correct after all. In any case, below is the assembly (comments with # added by me):

0000031e <analogWrite.part.0.constprop.2>:
# Note that the pin number is constant propagated, only the val is passed in r24
void analogWrite(uint8_t pin, int val)
 31e:   9c 01           movw    r18, r24
                switch(digitalPinToTimer(pin))
# This loads the timer value from a progmem table (item inside the table is at 0x01A7)
 320:   e7 ea           ldi     r30, 0xA7       ; 167
 322:   f1 e0           ldi     r31, 0x01       ; 1
 324:   e4 91           lpm     r30, Z
 # This checks for NOT_A_TIMER or similar, and jumps to 0x48c which handles that case
 326:   e1 50           subi    r30, 0x01       ; 1
 328:   e2 31           cpi     r30, 0x12       ; 18
 32a:   08 f0           brcs    .+2             ; 0x32e <analogWrite.part.0.constprop.2+0x10>
 32c:   af c0           rjmp    .+350           ; 0x48c <__LOCK_REGION_LENGTH__+0x8c>
# This is the jump table part. It takes the value returned by digitalPinToTimer(pin)
# (r30), extends it to r30:r31:r24 (little-endian, and adds 0x19c (by
# subtracting 0xfffe64, which wraps
# around to add 0x19c, which is half of 0x338 which is where the jump table
# starts). tablejump2 below then doubles this value, so it ends up looking
# at 0x338 + 2*digitalPinToTimer(pin), which makes sense since the jump table
# starts at 0x338 and each entry is 2 bytes (note that a timer 0 is invalid, so
# the table actually starts at 0x338 + 2).
 32e:   f0 e0           ldi     r31, 0x00       ; 0
 330:   88 27           eor     r24, r24
 332:   e4 56           subi    r30, 0x64       ; 100
 334:   fe 4f           sbci    r31, 0xFE       ; 254
 336:   8f 4f           sbci    r24, 0xFF       ; 255
 338:   ef c1           rjmp    .+990           ; 0x718 <__tablejump2__>
# This is the jump table, the first entry for digitalPinToTimer(pin) == 1
# This jumps to 0x01af (word address, so byte address 0x35e) which seems sane
 33a:   af 01           movw    r20, r30
 33c:   b4 01           movw    r22, r8
 33e:   b9 01           movw    r22, r18
 340:   c3 01           movw    r24, r6
 342:   cd 01           movw    r24, r26
 344:   46 02           muls    r20, r22
 346:   d7 01           movw    r26, r14
 348:   df 01           movw    r26, r30
 34a:   e7 01           movw    r28, r14
 34c:   f1 01           movw    r30, r2
 34e:   fb 01           movw    r30, r22
 350:   05 02           muls    r16, r21
 352:   14 02           muls    r17, r20
 354:   1e 02           muls    r17, r30
 356:   46 02           muls    r20, r22
 358:   28 02           muls    r18, r24
 35a:   32 02           muls    r19, r18
 35c:   3c 02           muls    r19, r28

# The jump table ends here, and this is the first case handler
                        case TIMER0A:
                                // connect pwm to pin on timer 0, channel A
                                sbi(TCCR0A, COM0A1);
 35e:   84 b5           in      r24, 0x24       ; 36
 360:   80 68           ori     r24, 0x80       ; 128
                                OCR0A = val; // set pwm duty
 362:   84 bd           out     0x24, r24       ; 36
 364:   27 bd           out     0x27, r18       ; 39
 366:   08 95           ret
# This function continues with more case handlers
...

00000718 <__tablejump2__>:
 718:   ee 0f           add     r30, r30
 71a:   ff 1f           adc     r31, r31
 71c:   88 1f           adc     r24, r24
# I suspect this is the RAMPZ register, which contains the upper bits for a
# > 16bits elpm (should be 0 here)
 71e:   8b bf           out     0x3b, r24       ; 59
 720:   07 90           elpm    r0, Z+
 722:   f6 91           elpm    r31, Z
 724:   e0 2d           mov     r30, r0
 726:   19 94           eijmp

I guess this either needs some debug prints (to read back various register values) or a JTAG debugger to verify what parts are correct and where the problem starts (or looking at the asm more closely and really verifying that all the values are correct). I probably won't have more time for this soon, though.

@matthijskooijman
Copy link
Collaborator

Also, it might be useful to run with -fno-jump-tables to see if that also prevents the problem.

@Rocketct
Copy link

okk @matthijskooijman @PaulStoffregen thank you, in meanwhile will discuss with @facchinm about next steps

@Rocketct
Copy link

@matthijskooijman tested with -fno-jump-tables and works properly

@Potul72
Copy link

Potul72 commented Mar 5, 2020

I have tested in IDE version 1.8.7, 1.8.9 and 1.8.12 and happens to all versions, so I do not understand how @alaqadi and @Nnambles could make it run in previous versions.

void setup() {
  // put your setup code here, to run once:
analogWrite (7, 100);
analogWrite (8, 200);

}

void loop() {
  // put your main code here, to run repeatedly:

}

This is what I am testing and with the oscilloscope I only see signal at pin 7...
imagen

@matthijskooijman
Copy link
Collaborator

@Potul72 Did you check the AVR core version used? If you upgraded that through the boards manager, a newer version is downloaded into your user folder, which then replaces the IDE-bundled version, even when you change the IDE version I think. However, if you do not have the AVR core in your user folder, it will use the IDE bundled version which will then change with IDE changes (usually).

To check, you can enable verbose compilation in the preferences, it should then use the AVR core version logged near the top of the compilation output.

Using the board manager, you can also easily test different AVR core versions without having to change the IDE version. You can revert to the bundled version, I think, by selecting the bundled version number in the board manager and "installing" it (I think this just throws away the version from the user folder, reverting to the IDE bundled version again).

@Potul72
Copy link

Potul72 commented Mar 6, 2020

Thanks @matthijskooijman. I have tested IDE version 1.8.5 with AVR core 1.8.2 and it failed also, then I tested IDE 1.8.5. with AVR core 1.6.12 and It work wounderfull. Then I tested latest IDE version 1.8.12 with AVR core 1.6.23 and it did work! So bug is on AVR Boards core from version 1.8.1, as there are no downloable version beween 1.6.23 and 1.8.1.

@WestfW
Copy link

WestfW commented Mar 7, 2020

I did a bit of tracing in the simulator. It looks like the code is ending up in the case for TIMER3B, when pin3 OUGHT to be TIMER3C - some sort off-by-one error in doing the jump table stuff?
Here's a dump of some of the code, and just before the jump to tablejump2, it looks like the "subtracted" constant for the "new" code is before the actual table? Some of the surrounding code has changed significantly, so it's hard to tell.

New:

// Right now, PWM output only works on the pins with
// hardware support.  These are defined in the appropriate
// pins_*.c file.  For the rest of the pins, we default
// to digital output.
void analogWrite(uint8_t pin, int val)
 31e:   9c 01           movw    r18, r24
        {
                digitalWrite(pin, HIGH);
        }
        else
        {
                switch(digitalPinToTimer(pin))
 320:   e7 ea           ldi     r30, 0xA7       ; 167
 322:   f1 e0           ldi     r31, 0x01       ; 1
 324:   e4 91           lpm     r30, Z
 326:   e1 50           subi    r30, 0x01       ; 1
 328:   e2 31           cpi     r30, 0x12       ; 18
 32a:   08 f0           brcs    .+2             ; 0x32e <analogWrite.part.0.constprop.2+0x10>
 32c:   af c0           rjmp    .+350           ; 0x48c <__LOCK_REGION_LENGTH__+0x8c>
 32e:   f0 e0           ldi     r31, 0x00       ; 0
 330:   88 27           eor     r24, r24
 332:   e4 56           subi    r30, 0x64       ; 100  24bits of (-(0x338 >> 1)), one word before jump table (?)
 334:   fe 4f           sbci    r31, 0xFE       ; 254     :
 336:   8f 4f           sbci    r24, 0xFF       ; 255       :
 338:   94 c1           rjmp    .+808           ; 0x662 <__tablejump2__>
 
 33a:   af 01           movw    r20, r30	; (case table) timer0a
 33c:   b4 01           movw    r22, r8
 33e:   b9 01           movw    r22, r18
 340:   c3 01           movw    r24, r6
 342:   cd 01           movw    r24, r26
 344:   46 02           muls    r20, r22
 346:   d7 01           movw    r26, r14
 348:   df 01           movw    r26, r30
 34a:   e7 01           movw    r28, r14
 34c:   f1 01           movw    r30, r2
 34e:   fb 01           movw    r30, r22
 350:   05 02           muls    r16, r21
 352:   14 02           muls    r17, r20

000001a4 <digital_pin_to_timer_PGM>:
 1a7:   02 09 0c 0d 0e 08 07 03 04 01 00 00     ................

Old:

        {
                digitalWrite(pin, HIGH);
 392:   81 e0           ldi     r24, 0x01       ; 1
 394:   61 cf           rjmp    .-318           ; 0x258 <digitalWrite.constprop.
2>
        }
        else
        {
                switch(digitalPinToTimer(pin))
 396:   ef ee           ldi     r30, 0xEF       ; 239
 398:   f1 e0           ldi     r31, 0x01       ; 1
 39a:   e4 91           lpm     r30, Z
 39c:   8e 2f           mov     r24, r30
 39e:   90 e0           ldi     r25, 0x00       ; 0
 3a0:   fc 01           movw    r30, r24
 3a2:   31 97           sbiw    r30, 0x01       ; 1
 3a4:   e2 31           cpi     r30, 0x12       ; 18
 3a6:   f1 05           cpc     r31, r1
 3a8:   08 f0           brcs    .+2             ; 0x3ac <analogWrite.constprop.0
+0x62>
 3aa:   9c c0           rjmp    .+312           ; 0x4e4 <__LOCK_REGION_LENGTH__+
0xe4>
 3ac:   88 27           eor     r24, r24
 3ae:   ec 57           subi    r30, 0x7C       ; 124 24bits of (-(0x108 >> 1)), one word before jump table (?)
 3b0:   ff 4f           sbci    r31, 0xFF       ; 255   :
 3b2:   8f 4f           sbci    r24, 0xFF       ; 255     :
 3b4:   63 c1           rjmp    .+710           ; 0x67c <__tablejump2__>

; timer table
000001ec <digital_pin_to_timer_PGM>:
 1ef:   02 09 0c 0d 0e 08 07 03 04 01 00 00

; case table earlier in memory:
 108:   db 01           movw    r26, r22  ;timer0a case
 10a:   e0 01           movw    r28, r0	  ;timer0b case
 10c:   e5 01           movw    r28, r10  ;timer1a case
 10e:   ef 01           movw    r28, r30  ;timer1b case
 110:   f9 01           movw    r30, r18  ;timer1c case
 112:   72 02           muls    r23, r18
 114:   03 02           muls    r16, r19
 116:   0b 02           muls    r16, r27
 118:   13 02           muls    r17, r19
 11a:   1d 02           muls    r17, r29
 11c:   27 02           muls    r18, r23
 11e:   31 02           muls    r19, r17
 120:   40 02           muls    r20, r16
 122:   4a 02           muls    r20, r26
 124:   72 02           muls    r23, r18
 126:   54 02           muls    r21, r20
 128:   5e 02           muls    r21, r30
 12a:   68 02           muls    r22, r24

@igendel
Copy link

igendel commented Mar 8, 2020

Hello, excuse me for the interruption - I stumbled upon this issue lately and found this thread... if it helps in any way to pinpoint the source of the problem, I noticed that when I pass the duty cycle parameter to analogWrite using a variable declared as volatile, the problem disappears. Probably related to the optimization settings @Rocketct mentioned above.

@victor045
Copy link

Hello, I can confirm that the issue happened to me with the IDE versions 1.8.10, and 1.8.13.
It worked with the previous 1.8.8 version.

@ghost
Copy link

ghost commented Mar 24, 2020

The issue is definitely confirmed for IDEs 1.8.10 and higher. Just try to run this simple sketch on Mega2560

void setup(void) {
	analogWrite(6, 100);
	analogWrite(5, 200);
}

void loop(void) {}

and make sure - there is no PWM on those pins.

### The workaround is found!

Open the file "platform.txt" and remove all the options concerned to lto. Just look for "lto" with context search and remove all of them.

That's all. Have a nice day!

@Potul72
Copy link

Potul72 commented Apr 29, 2020

Thanks @elilitko! just let me clarify for other users (beginers like me) to remove only the options -lto and -flto. ... I removed the complete line ... and only the one containing -lto ...

@biro-mark
Copy link

Confirmed this issue with Windows 10, Arduino 1.8.12 (Windows Store 1.8.33.0)

https://arduino.stackexchange.com/questions/75338/mega-2560-simple-program-one-analogwrite-turns-off-the-other

@matthijskooijman
Copy link
Collaborator

I think this is a problem that we should somehow tackle. How about:

  • Adding -fno-jump-tables to the compilation options to prevent it from happening? This can hurt performance of big switch tables, but should otherwise not affect sketch performance much I think, so I would say this is acceptable for now. @facchinm, @PaulStoffregen, what would you think?
  • Trying to make a minimized example out of this, so we can report a bug at gcc upstream? With minimized, I do not mean a small sketch, but plain .c / .cpp files that can be fed directly to gcc without needing any Arduino code. Anyone want to have a stab at this? I won't have time in near future...
  • Moving this issue to ArduinoCore-avr?

@facchinm
Copy link
Member

facchinm commented May 4, 2020

  1. I think it's a good workaround we can implement immediately
  2. gcc upstream status is a bit cumbersome now (since they called for removal of the AVR backend)
  3. absolutely, doing it now 😉

@facchinm facchinm pinned this issue May 4, 2020
@facchinm facchinm unpinned this issue May 4, 2020
@facchinm facchinm transferred this issue from arduino/Arduino May 4, 2020
@WestfW
Copy link

WestfW commented May 5, 2020

I've created a minimalized source tree and build scripts for working on this in https://github.com/WestfW/Duino-hacks/tree/master/pwmbug
These:

  1. bypass the IDE build process
  2. include a minimalized source tree that produces identical code to an IDE build
  3. have several build scripts for comparing object files.

(no actual results yet.)

@WestfW
Copy link

WestfW commented May 7, 2020

I've further consolidated the minimalized source, end up with a "consolidate" version that has one .cpp file and one .c file, each already pre-processed. (main.cpp has the main.cpp and sketch code, wiring_all.c has the necessary parts of wiring.c, wiring_digital.c, wiring_analog.c)
And I checked the .hex file to confirm it exhibits the bug on live hardware.
github repository updated, and minimal form attached...
pwmbug.zip

It's still pretty mysterious. For example, it will start working if the code for turnOffPWM() is commented out.

@WestfW
Copy link

WestfW commented May 8, 2020

It certainly looks like an off-by-one error in calculating the start of the jump table, as theorized in #339 (comment)

What's weird is that it doesn't seem to happen for the non-lto case, doesn't happen when there is only a single analogWrite() call, and (NEW DATA!) doesn't happen if the -relax option is removed from the link command.

-relax causes certain long jumps/calls to be shortened to rjmp/rcall. Perhaps the intermediate representations passed to the linker with -flto are missing information as to locations that need "fixed up" after "relaxing" ?

This is pretty much as far as I can go. I have no knowledge or understanding of avr-gcc internal operations...

@matthijskooijman
Copy link
Collaborator

What's weird is that it doesn't seem to happen for the non-lto case, doesn't happen when there is only a single analogWrite() call, and (NEW DATA!) doesn't happen if the -relax option is removed from the link command.

Ah, that is awesome new info, since that gives a very strong indication of what is happening here (jump tables getting messed up by jump relaxation).

I had hoped that this extra info might turn up an existing bug report about this, but no such luck it seems.

The minimized example also looks good. Not sure if it is minimal enough yet for a gcc bugreport, I suspect that there are still some definitions and declarations that can be removed? Also, it would be good if the generated assembly is simple enough so the problem can be shown based on that, rather than having to run the code, but that might be tricky and/or cause the problem to disappear...

One thing that could maybe help is to pass --param case-values-threshold=1 to gcc, to make it generate a jump table for all switches (i.e. set the minimum number of case labels for using a jumptable to 1). Maybe with that, a minimal example could be constructed rather than basing on the existing example, or the existing example could be further reduced?

Can we test this on newer gcc versions (or did we already)? It seems Arduino now ships 7.3.0, not sure if there are any versions available in staging or elsewhere? Debian only has 5.4.0 it seems...

@hb9tst
Copy link

hb9tst commented May 28, 2020

Just discovered this issue after trying to figure out for hours what was wrong with PWM. It is a very annoying bug... especially that I knew that all this was working in the past!

From what I could observe in my tests (on two Mega2560 R3 boards), as soon as there is a second call to analogWrite() that is compiled (unless it is identical to the first one), all calls are not working at all, any only a flat 0V signal is observed with the oscilloscope on the corresponding output pin.

This code works fine:

void setup() {
  pinMode(2, OUTPUT);
  analogWrite(2, 42);
}

This works too:

void setup() {
  pinMode(2, OUTPUT);
  analogWrite(2, 42);
  analogWrite(2, 42);
}

This does not work:

void setup() {
  pinMode(2, OUTPUT);
  analogWrite(2, 42);
  analogWrite(2, 84);
}

This works, as the second call is optimized out:

void setup() {
  pinMode(2, OUTPUT);
  analogWrite(2, 42);
  if (1 == 0) {
    analogWrite(2, 84);
  }
}

This does not work as the second call is not optimized out by the compiler:

int x = 12;

void setup() {
  pinMode(2, OUTPUT);
  analogWrite(2, 42);
  if (x == 0) {
    analogWrite(2, 84);
  }
}

What is surprising is that the second call to analogWrite never happens, because x is not zero. However, the fact that the call is present seems to be sufficient for the compiler to generate buggy code. I confirmed using Serial.println() that the code in the if statement is never executed.

In all cases my loop() was empty, or contained calls to Serial.println(), which didn't influence the behaviour of analogWrite(). Unfortunately I don't have time to compare the generated assembly code, also because my knowledge of AVR assembly is very superficial.

Inserting a declaration to force the optimization level of the setup() function to 1 solves the issue (at least for calls from setup()):

void setup() __attribute__((optimize("-O1")));

I also tried with -O2, but in this case the bug is present.

cmaglie added a commit to arduino/arduino-cli that referenced this issue Jun 12, 2020
This removes the --relax option, potentially producing slightly bigger code for the atmega2560. On the longer term, the AVR core should just add this option for all boards, but this is not currently the case yet because removing --relax also works around a gcc miscompilation (see arduino/ArduinoCore-avr#339).

Close: #639
umbynos pushed a commit to arduino/arduino-cli that referenced this issue Jun 17, 2020
This removes the --relax option, potentially producing slightly bigger code for the atmega2560. On the longer term, the AVR core should just add this option for all boards, but this is not currently the case yet because removing --relax also works around a gcc miscompilation (see arduino/ArduinoCore-avr#339).

Close: #639
@facchinm
Copy link
Member

Should be fixed by avr core 1.8.3 + IDE 1.8.13 ; updating to the new IDE is important since it ships with this patch (on the tooling side).
If people previously experiencing the problem could report here if they still have troubles it would be great.
In the meantime, I'm closing this as fixed.

@matthijskooijman
Copy link
Collaborator

For completeness, this is not actually fixed (the bug still exists in gcc), we just removed the circumstances that trigger this bug. Small (but IMHO relevant) difference. Any third party cores that would add --relax manually would still be affected too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests